Changes in / [f988834:59c8dff]
- Files:
-
- 6 deleted
- 42 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/LaTeXmacros/common.sty
rf988834 r59c8dff 11 11 %% Created On : Sat Apr 9 10:06:17 2016 12 12 %% Last Modified By : Peter A. Buhr 13 %% Last Modified On : Sun Jan 14 12:28:26 202414 %% Update Count : 63113 %% Last Modified On : Fri Sep 29 16:48:59 2023 14 %% Update Count : 587 15 15 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 16 … … 273 273 \setlength{\columnposn}{\gcolumnposn} 274 274 \newcommand{\setgcolumn}[1]{\global\gcolumnposn=#1\global\columnposn=\gcolumnposn} 275 \newcommand{\C}[2][\@empty]{\ifx#1\@empty\else\global\setlength{\columnposn}{#1}\global\columnposn=\columnposn\fi\hfill\makebox[\textwidth-\columnposn][l]{\LstCommentStyle{#2}}} 276 \newcommand{\CD}[2][\@empty]{\ifx#1\@empty\else\global\setlength{\columnposn}{#1}\global\columnposn=\columnposn\fi\hfill\makebox[\textwidth-\columnposn][l]{\LstBasicStyle{#2}}} 275 \newcommand{\C}[2][\@empty]{\ifx#1\@empty\else\global\setlength{\columnposn}{#1}\global\columnposn=\columnposn\fi\hfill\makebox[\textwidth-\columnposn][l]{\lst@basicstyle{\LstCommentStyle{#2}}}} 277 276 \newcommand{\CRT}{\global\columnposn=\gcolumnposn} 278 277 … … 293 292 xleftmargin=\parindentlnth, % indent code to paragraph indentation 294 293 extendedchars=true, % allow ASCII characters in the range 128-255 295 escapechar= §, % LaTeX escape in CFA code §...§ (section symbol), emacs: C-q M-'294 escapechar=\$, % LaTeX escape in CFA code §...§ (section symbol), emacs: C-q M-' 296 295 mathescape=false, % disable LaTeX math escape in CFA code $...$ 297 296 keepspaces=true, % … … 303 302 % replace/adjust listing characters that look bad in sanserif 304 303 literate= 305 % {-}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.75ex}{0.1ex}}}}1 306 {-}{\raisebox{-1pt}{\texttt{-}}}1 304 {-}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.75ex}{0.1ex}}}}1 307 305 {^}{\raisebox{0.6ex}{$\scriptstyle\land\,$}}1 308 306 {~}{\raisebox{0.3ex}{$\scriptstyle\sim\,$}}1 … … 310 308 {<-}{$\leftarrow$}2 311 309 {=>}{$\Rightarrow$}2 312 % {->}{\raisebox{-1pt}{\texttt{-}}\kern-0.1ex\textgreater}2,310 {->}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.8ex}{0.075ex}}}\kern-0.2ex\textgreater}2, 313 311 }% lstset 314 312 }% CFAStyle -
doc/LaTeXmacros/common.tex
rf988834 r59c8dff 11 11 %% Created On : Sat Apr 9 10:06:17 2016 12 12 %% Last Modified By : Peter A. Buhr 13 %% Last Modified On : Sun Jan 14 17:59:02 202414 %% Update Count : 59 213 %% Last Modified On : Fri Sep 29 16:49:02 2023 14 %% Update Count : 590 15 15 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 16 … … 276 276 \setlength{\columnposn}{\gcolumnposn} 277 277 \newcommand{\setgcolumn}[1]{\global\gcolumnposn=#1\global\columnposn=\gcolumnposn} 278 \newcommand{\C}[2][\@empty]{\ifx#1\@empty\else\global\setlength{\columnposn}{#1}\global\columnposn=\columnposn\fi\hfill\makebox[\textwidth-\columnposn][l]{\LstCommentStyle{#2}}} 279 \newcommand{\CD}[2][\@empty]{\ifx#1\@empty\else\global\setlength{\columnposn}{#1}\global\columnposn=\columnposn\fi\hfill\makebox[\textwidth-\columnposn][l]{\LstBasicStyle{#2}}} 278 \newcommand{\C}[2][\@empty]{\ifx#1\@empty\else\global\setlength{\columnposn}{#1}\global\columnposn=\columnposn\fi\hfill\makebox[\textwidth-\columnposn][l]{\lst@basicstyle{\LstCommentStyle{#2}}}} 280 279 \newcommand{\CRT}{\global\columnposn=\gcolumnposn} 281 280 … … 297 296 xleftmargin=\parindentlnth, % indent code to paragraph indentation 298 297 extendedchars=true, % allow ASCII characters in the range 128-255 299 escapechar= §, % LaTeX escape in CFA code §...§ (section symbol), emacs: C-q M-'298 escapechar=\$, % LaTeX escape in CFA code §...§ (section symbol), emacs: C-q M-' 300 299 mathescape=false, % disable LaTeX math escape in CFA code $...$ 301 300 keepspaces=true, % … … 307 306 % replace/adjust listing characters that look bad in sanserif 308 307 literate= 309 % {-}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.75ex}{0.1ex}}}}1 310 {-}{\raisebox{-1pt}{\texttt{-}}}1 308 {-}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.75ex}{0.1ex}}}}1 311 309 {^}{\raisebox{0.6ex}{$\scriptstyle\land\,$}}1 312 310 {~}{\raisebox{0.3ex}{$\scriptstyle\sim\,$}}1 … … 314 312 {<-}{$\leftarrow$}2 315 313 {=>}{$\Rightarrow$}2 316 % {->}{\raisebox{-1pt}{\texttt{-}}\kern-0.1ex\textgreater}2,314 {->}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.8ex}{0.075ex}}}\kern-0.2ex\textgreater}2, 317 315 }% lstset 318 316 }% CFAStyle -
doc/user/user.tex
rf988834 r59c8dff 11 11 %% Created On : Wed Apr 6 14:53:29 2016 12 12 %% Last Modified By : Peter A. Buhr 13 %% Last Modified On : S un Jan 14 17:27:41 202414 %% Update Count : 5 76413 %% Last Modified On : Sat Sep 30 22:46:19 2023 14 %% Update Count : 5658 15 15 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 16 … … 55 55 \SetWatermarkLightness{0.9} 56 56 57 % Default underscore is too low. Cannot use lstlisting "literate" as replacing underscore removes it 58 % as a variable-name character so keywords in variables are highlighted. MUST APPEAR AFTER HYPERREF. 59 \renewcommand{\textunderscore}{\makebox[1.4ex][c]{{\raisebox{1.25pt}{\char`\_}}}} 57 % Default underscore is too low and wide. Cannot use lstlisting "literate" as replacing underscore 58 % removes it as a variable-name character so keywords in variables are highlighted. MUST APPEAR 59 % AFTER HYPERREF. 60 \renewcommand{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.075ex}}} 60 61 61 62 \setlength{\topmargin}{-0.45in} % move running title into header … … 66 67 \CFAStyle % use default CFA format-style 67 68 \setgcolumn{2.25in} 68 \lstset{language=CFA} % CFA default lnaguage69 %\lstset{language=CFA} % CFA default lnaguage 69 70 \lstnewenvironment{C++}[1][] % use C++ style 70 71 {\lstset{language=C++,moredelim=**[is][\protect\color{red}]{®}{®},#1}} … … 171 172 \begin{tabular}{@{}lll@{}} 172 173 \multicolumn{1}{@{}c}{\textbf{C}} & \multicolumn{1}{c}{\textbf{\CFA}} & \multicolumn{1}{c@{}}{\textbf{\CC}} \\ 173 \begin{cfa} 174 #include <stdio.h> §\indexc{stdio.h}§174 \begin{cfa}[tabsize=3] 175 #include <stdio.h>$\indexc{stdio.h}$ 175 176 176 177 int main( void ) { … … 181 182 & 182 183 \begin{cfa}[tabsize=3] 183 #include <fstream> §\indexc{fstream}§184 #include <fstream>$\indexc{fstream}$ 184 185 185 186 int main( void ) { 186 187 int x = 0, y = 1, z = 2; 187 ®sout | x | y | z;® §\indexc{sout}§188 ®sout | x | y | z;®$\indexc{sout}$ 188 189 } 189 190 \end{cfa} 190 191 & 191 192 \begin{cfa}[tabsize=3] 192 #include <iostream> §\indexc{iostream}§193 #include <iostream>$\indexc{iostream}$ 193 194 using namespace std; 194 195 int main() { … … 259 260 \begin{cfa} 260 261 ®forall( T )® T identity( T val ) { return val; } 261 int forty_two = identity( 42 ); §\C{// T is bound to int, forty\_two == 42}§262 int forty_two = identity( 42 ); $\C{// T is bound to int, forty\_two == 42}$ 262 263 \end{cfa} 263 264 % extending the C type system with parametric polymorphism and overloading, as opposed to the \Index*[C++]{\CC{}} approach of object-oriented extensions. … … 287 288 288 289 double key = 5.0, vals[10] = { /* 10 sorted floating values */ }; 289 double * val = (double *)bsearch( &key, vals, 10, sizeof(vals[0]), comp ); §\C{// search sorted array}§290 double * val = (double *)bsearch( &key, vals, 10, sizeof(vals[0]), comp ); $\C{// search sorted array}$ 290 291 \end{cfa} 291 292 which can be augmented simply with a polymorphic, type-safe, \CFA-overloaded wrappers: … … 296 297 297 298 forall( T | { int ?<?( T, T ); } ) unsigned int bsearch( T key, const T * arr, size_t size ) { 298 T * result = bsearch( key, arr, size ); §\C{// call first version}§299 return result ? result - arr : size; } §\C{// pointer subtraction includes sizeof(T)}§300 301 double * val = bsearch( 5.0, vals, 10 ); §\C{// selection based on return type}§299 T * result = bsearch( key, arr, size ); $\C{// call first version}$ 300 return result ? result - arr : size; } $\C{// pointer subtraction includes sizeof(T)}$ 301 302 double * val = bsearch( 5.0, vals, 10 ); $\C{// selection based on return type}$ 302 303 int posn = bsearch( 5.0, vals, 10 ); 303 304 \end{cfa} … … 311 312 \begin{cfa} 312 313 forall( dtype T | sized(T) ) T * malloc( void ) { return (T *)malloc( sizeof(T) ); } 313 int * ip = malloc(); §\C{// select type and size from left-hand side}§314 int * ip = malloc(); $\C{// select type and size from left-hand side}$ 314 315 double * dp = malloc(); 315 316 struct S {...} * sp = malloc(); … … 323 324 \begin{cfa} 324 325 char ®abs®( char ); 325 extern "C" { int ®abs®( int ); } §\C{// use default C routine for int}§326 extern "C" { int ®abs®( int ); } $\C{// use default C routine for int}$ 326 327 long int ®abs®( long int ); 327 328 long long int ®abs®( long long int ); … … 348 349 The command ©cfa© is used to compile a \CFA program and is based on the \Index{GNU} \Indexc{gcc} command, \eg: 349 350 \begin{cfa} 350 cfa §\indexc{cfa}\index{compilation!cfa@©cfa©}§ [ gcc/§\CFA{}§-options ] [ C/§\CFA{}§source-files ] [ assembler/loader files ]351 cfa$\indexc{cfa}\index{compilation!cfa@©cfa©}$ [ gcc/$\CFA{}$-options ] [ C/$\CFA{}$ source-files ] [ assembler/loader files ] 351 352 \end{cfa} 352 353 There is no ordering among options (flags) and files, unless an option has an argument, which must appear immediately after the option possibly with or without a space separating option and argument. … … 437 438 \begin{cfa} 438 439 #ifndef __CFORALL__ 439 #include <stdio.h> §\indexc{stdio.h}§ §\C{// C header file}§440 #include <stdio.h>$\indexc{stdio.h}$ $\C{// C header file}$ 440 441 #else 441 #include <fstream> §\indexc{fstream}§ §\C{// \CFA header file}§442 #include <fstream>$\indexc{fstream}$ $\C{// \CFA header file}$ 442 443 #endif 443 444 \end{cfa} … … 449 450 Each option must be escaped with \Indexc{-XCFA}\index{translator option!-XCFA@{©-XCFA©}} to direct it to the compiler step, similar to the ©-Xlinker© flag for the linker, \eg: 450 451 \begin{lstlisting}[language=sh] 451 cfa §test§.cfa -CFA -XCFA -p # print translated code without printing the standard prelude452 cfa §test§.cfa -XCFA -P -XCFA parse -XCFA -n # show program parse without prelude452 cfa $test$.cfa -CFA -XCFA -p # print translated code without printing the standard prelude 453 cfa $test$.cfa -XCFA -P -XCFA parse -XCFA -n # show program parse without prelude 453 454 \end{lstlisting} 454 Alternatively, multiple flag s can be specified separated with commas and \emph{without} spaces.455 Alternatively, multiple flages can be specified separated with commas and \emph{without} spaces. 455 456 \begin{lstlisting}[language=sh,{moredelim=**[is][\protect\color{red}]{®}{®}}] 456 cfa §test§.cfa -XCFA®,®-Pparse®,®-n # show program parse without prelude457 cfa $test$.cfa -XCFA®,®-Pparse®,®-n # show program parse without prelude 457 458 \end{lstlisting} 458 459 \begin{description}[topsep=5pt,itemsep=0pt,parsep=0pt] … … 536 537 Keyword clashes are accommodated by syntactic transformations using the \CFA backquote escape-mechanism: 537 538 \begin{cfa} 538 int ®``®coroutine = 3; §\C{// make keyword an identifier}§539 int ®``®coroutine = 3; $\C{// make keyword an identifier}$ 539 540 double ®``®forall = 3.5; 540 541 \end{cfa} … … 546 547 \begin{cfa} 547 548 // include file uses the CFA keyword "with". 548 #if ! defined( with ) §\C{// nesting ?}§549 #define with ®``®with §\C{// make keyword an identifier}§549 #if ! defined( with ) $\C{// nesting ?}$ 550 #define with ®``®with $\C{// make keyword an identifier}$ 550 551 #define __CFA_BFD_H__ 551 552 #endif 552 §\R{\#include\_next} <bfdlink.h>§ §\C{// must have internal check for multiple expansion}§ 553 #if defined( with ) && defined( __CFA_BFD_H__ ) §\C{// reset only if set}§553 $\R{\#include\_next} <bfdlink.h>$ $\C{// must have internal check for multiple expansion}$ 554 #if defined( with ) && defined( __CFA_BFD_H__ ) $\C{// reset only if set}$ 554 555 #undef with 555 556 #undef __CFA_BFD_H__ … … 565 566 Numeric constants are extended to allow \Index{underscore}s\index{constant!underscore} as a separator, \eg: 566 567 \begin{cfa} 567 2®_®147®_®483®_®648; §\C{// decimal constant}§568 56®_®ul; §\C{// decimal unsigned long constant}§569 0®_®377; §\C{// octal constant}§570 0x®_®ff®_®ff; §\C{// hexadecimal constant}§571 0x®_®ef3d®_®aa5c; §\C{// hexadecimal constant}§572 3.141®_®592®_®654; §\C{// floating constant}§573 10®_®e®_®+1®_®00; §\C{// floating constant}§574 0x®_®ff®_®ff®_®p®_®3; §\C{// hexadecimal floating}§575 0x®_®1.ffff®_®ffff®_®p®_®128®_®l; §\C{// hexadecimal floating long constant}§576 L®_® §"\texttt{\textbackslash{x}}§®_®§\texttt{ff}§®_®§\texttt{ee}"§; §\C{// wide character constant}§568 2®_®147®_®483®_®648; $\C{// decimal constant}$ 569 56®_®ul; $\C{// decimal unsigned long constant}$ 570 0®_®377; $\C{// octal constant}$ 571 0x®_®ff®_®ff; $\C{// hexadecimal constant}$ 572 0x®_®ef3d®_®aa5c; $\C{// hexadecimal constant}$ 573 3.141®_®592®_®654; $\C{// floating constant}$ 574 10®_®e®_®+1®_®00; $\C{// floating constant}$ 575 0x®_®ff®_®ff®_®p®_®3; $\C{// hexadecimal floating}$ 576 0x®_®1.ffff®_®ffff®_®p®_®128®_®l; $\C{// hexadecimal floating long constant}$ 577 L®_®$"\texttt{\textbackslash{x}}$®_®$\texttt{ff}$®_®$\texttt{ee}"$; $\C{// wide character constant}$ 577 578 \end{cfa} 578 579 The rules for placement of underscores are: … … 634 635 Declarations in the \Indexc{do}-©while© condition are not useful because they appear after the loop body.} 635 636 \begin{cfa} 636 if ( ®int x = f()® ) ... §\C{// x != 0}§637 if ( ®int x = f(), y = g()® ) ... §\C{// x != 0 \&\& y != 0}§638 if ( ®int x = f(), y = g(); x < y® ) ... §\C{// relational expression}§639 if ( ®struct S { int i; } x = { f() }; x.i < 4® ) §\C{// relational expression}§640 641 while ( ®int x = f()® ) ... §\C{// x != 0}§642 while ( ®int x = f(), y = g()® ) ... §\C{// x != 0 \&\& y != 0}§643 while ( ®int x = f(), y = g(); x < y® ) ... §\C{// relational expression}§644 while ( ®struct S { int i; } x = { f() }; x.i < 4® ) ... §\C{// relational expression}§637 if ( ®int x = f()® ) ... $\C{// x != 0}$ 638 if ( ®int x = f(), y = g()® ) ... $\C{// x != 0 \&\& y != 0}$ 639 if ( ®int x = f(), y = g(); x < y® ) ... $\C{// relational expression}$ 640 if ( ®struct S { int i; } x = { f() }; x.i < 4® ) $\C{// relational expression}$ 641 642 while ( ®int x = f()® ) ... $\C{// x != 0}$ 643 while ( ®int x = f(), y = g()® ) ... $\C{// x != 0 \&\& y != 0}$ 644 while ( ®int x = f(), y = g(); x < y® ) ... $\C{// relational expression}$ 645 while ( ®struct S { int i; } x = { f() }; x.i < 4® ) ... $\C{// relational expression}$ 645 646 \end{cfa} 646 647 Unless a relational expression is specified, each variable is compared not equal to 0, which is the standard semantics for the ©if©/©while© expression, and the results are combined using the logical \Indexc{&&} operator. … … 712 713 \begin{cfa} 713 714 switch ( i ) { 714 case 1 §\R{\textvisiblespace}§®...®4:715 case 1$\R{\textvisiblespace}$®...®4: 715 716 ... 716 case 10 §\R{\textvisiblespace}§®...®13:717 case 10$\R{\textvisiblespace}$®...®13: 717 718 ... 718 719 } … … 751 752 case 1: 752 753 ... 753 §\R{\LstCommentStyle{// fall-through}}§754 $\R{\LstCommentStyle{// fall-through}}$ 754 755 case 2: 755 756 ... … … 852 853 \begin{cfa} 853 854 switch ( x ) { 854 ®int y = 1;® §\C{// unreachable initialization}§855 ®x = 7;® §\C{// unreachable code without label/branch}§855 ®int y = 1;® $\C{// unreachable initialization}$ 856 ®x = 7;® $\C{// unreachable code without label/branch}$ 856 857 case 0: ... 857 858 ... 858 ®int z = 0;® §\C{// unreachable initialization, cannot appear after case}§859 ®int z = 0;® $\C{// unreachable initialization, cannot appear after case}$ 859 860 z = 2; 860 861 case 1: 861 ®x = z;® §\C{// without fall through, z is uninitialized}§862 ®x = z;® $\C{// without fall through, z is uninitialized}$ 862 863 } 863 864 \end{cfa} … … 894 895 case 1: case 2: case 3: 895 896 ... 896 §\R{\LstCommentStyle{// implicit end of switch (break)}}§897 $\R{\LstCommentStyle{// implicit end of switch (break)}}$ 897 898 case 5: 898 899 ... 899 ®fallthru®; §\C{// explicit fall through}§900 ®fallthru®; $\C{// explicit fall through}$ 900 901 case 7: 901 902 ... 902 ®break® §\C{// explicit end of switch (redundant)}§903 ®break® $\C{// explicit end of switch (redundant)}$ 903 904 default: 904 905 j = 3; … … 921 922 \begin{cfa} 922 923 switch ( x ) { 923 ®int i = 0;® §\C{// allowed only at start}§924 ®int i = 0;® $\C{// allowed only at start}$ 924 925 case 0: 925 926 ... 926 ®int j = 0;® §\C{// disallowed}§927 ®int j = 0;® $\C{// disallowed}$ 927 928 case 1: 928 929 { 929 ®int k = 0;® §\C{// allowed at different nesting levels}§930 ®int k = 0;® $\C{// allowed at different nesting levels}$ 930 931 ... 931 ®case 2:® §\C{// disallow case in nested statements}§932 ®case 2:® $\C{// disallow case in nested statements}$ 932 933 } 933 934 ... … … 1003 1004 while () { sout | "empty"; break; } 1004 1005 do { sout | "empty"; break; } while (); 1005 for () { sout | "empty"; break; } §\C[3in]{sout | nl | nlOff;}§1006 1007 for ( 0 ) { sout | "A"; } sout | "zero"; §\C{sout | nl;}§1008 for ( 1 ) { sout | "A"; } §\C{sout | nl;}§1009 for ( 10 ) { sout | "A"; } §\C{sout | nl;}§1010 for ( ~= 10 ) { sout | "A"; } §\C{sout | nl;}§1011 for ( 1 ~= 10 ~ 2 ) { sout | "B"; } §\C{sout | nl;}§1012 for ( 1 -~= 10 ~ 2 ) { sout | "C"; } §\C{sout | nl;}§1013 for ( 0.5 ~ 5.5 ) { sout | "D"; } §\C{sout | nl;}§1014 for ( 0.5 -~ 5.5 ) { sout | "E"; } §\C{sout | nl;}§1015 for ( i; 10 ) { sout | i; } §\C{sout | nl;}§1016 for ( i; ~= 10 ) { sout | i; } §\C{sout | nl;}§1017 for ( i; 1 ~= 10 ~ 2 ) { sout | i; } §\C{sout | nl;}§1018 for ( i; 1 -~= 10 ~ 2 ) { sout | i; } §\C{sout | nl;}§1019 for ( i; 0.5 ~ 5.5 ) { sout | i; } §\C{sout | nl;}§1020 for ( i; 0.5 -~ 5.5 ) { sout | i; } §\C{sout | nl;}§1021 for ( ui; 2u ~= 10u ~ 2u ) { sout | ui; } §\C{sout | nl;}§1022 for ( ui; 2u -~= 10u ~ 2u ) { sout | ui; } §\C{sout | nl | nl | nl;}§1006 for () { sout | "empty"; break; } $\C[3in]{sout | nl | nlOff;}$ 1007 1008 for ( 0 ) { sout | "A"; } sout | "zero"; $\C{sout | nl;}$ 1009 for ( 1 ) { sout | "A"; } $\C{sout | nl;}$ 1010 for ( 10 ) { sout | "A"; } $\C{sout | nl;}$ 1011 for ( ~= 10 ) { sout | "A"; } $\C{sout | nl;}$ 1012 for ( 1 ~= 10 ~ 2 ) { sout | "B"; } $\C{sout | nl;}$ 1013 for ( 1 -~= 10 ~ 2 ) { sout | "C"; } $\C{sout | nl;}$ 1014 for ( 0.5 ~ 5.5 ) { sout | "D"; } $\C{sout | nl;}$ 1015 for ( 0.5 -~ 5.5 ) { sout | "E"; } $\C{sout | nl;}$ 1016 for ( i; 10 ) { sout | i; } $\C{sout | nl;}$ 1017 for ( i; ~= 10 ) { sout | i; } $\C{sout | nl;}$ 1018 for ( i; 1 ~= 10 ~ 2 ) { sout | i; } $\C{sout | nl;}$ 1019 for ( i; 1 -~= 10 ~ 2 ) { sout | i; } $\C{sout | nl;}$ 1020 for ( i; 0.5 ~ 5.5 ) { sout | i; } $\C{sout | nl;}$ 1021 for ( i; 0.5 -~ 5.5 ) { sout | i; } $\C{sout | nl;}$ 1022 for ( ui; 2u ~= 10u ~ 2u ) { sout | ui; } $\C{sout | nl;}$ 1023 for ( ui; 2u -~= 10u ~ 2u ) { sout | ui; } $\C{sout | nl | nl | nl;}$ 1023 1024 1024 1025 enum { N = 10 }; 1025 for ( N ) { sout | "N"; } §\C{sout | nl;}§1026 for ( i; N ) { sout | i; } §\C{sout | nl;}§1027 for ( i; -~ N ) { sout | i; } §\C{sout | nl | nl | nl;}§1026 for ( N ) { sout | "N"; } $\C{sout | nl;}$ 1027 for ( i; N ) { sout | i; } $\C{sout | nl;}$ 1028 for ( i; -~ N ) { sout | i; } $\C{sout | nl | nl | nl;}$ 1028 1029 1029 1030 const int low = 3, high = 10, inc = 2; 1030 for ( i; low ~ high ~ inc + 1 ) { sout | i; } §\C{sout | nl;}§1031 for ( i; 1 ~ @ ) { if ( i > 10 ) break; sout | i; } §\C{sout | nl;}§1032 for ( i; @ -~ 10 ) { if ( i < 0 ) break; sout | i; } §\C{sout | nl;}§1033 for ( i; 2 ~ @ ~ 2 ) { if ( i > 10 ) break; sout | i; } §\C{sout | nl;}§1034 for ( i; 2.1 ~ @ ~ @ ) { if ( i > 10.5 ) break; sout | i; i += 1.7; } §\C{sout | nl;}§1035 for ( i; @ -~ 10 ~ 2 ) { if ( i < 0 ) break; sout | i; } §\C{sout | nl;}§1036 for ( i; 12.1 ~ @ ~ @ ) { if ( i < 2.5 ) break; sout | i; i -= 1.7; } §\C{sout | nl;}§1037 for ( i; 5 : j; -5 ~ @ ) { sout | i | j; } §\C{sout | nl;}§1038 for ( i; 5 : j; @ -~ -5 ) { sout | i | j; } §\C{sout | nl;}§1039 for ( i; 5 : j; -5 ~ @ ~ 2 ) { sout | i | j; } §\C{sout | nl;}§1040 for ( i; 5 : j; @ -~ -5 ~ 2 ) { sout | i | j; } §\C{sout | nl;}§1041 for ( i; 5 : j; -5 ~ @ ) { sout | i | j; } §\C{sout | nl;}§1042 for ( i; 5 : j; @ -~ -5 ) { sout | i | j; } §\C{sout | nl;}§1043 for ( i; 5 : j; -5 ~ @ ~ 2 ) { sout | i | j; } §\C{sout | nl;}§1044 for ( i; 5 : j; @ -~ -5 ~ 2 ) { sout | i | j; } §\C{sout | nl;}§1045 for ( i; 5 : j; @ -~ -5 ~ 2 : k; 1.5 ~ @ ) { sout | i | j | k; } §\C{sout | nl;}§1046 for ( i; 5 : j; @ -~ -5 ~ 2 : k; 1.5 ~ @ ) { sout | i | j | k; } §\C{sout | nl;}§1047 for ( i; 5 : k; 1.5 ~ @ : j; @ -~ -5 ~ 2 ) { sout | i | j | k; } §\C{sout | nl;}\CRT§1031 for ( i; low ~ high ~ inc + 1 ) { sout | i; } $\C{sout | nl;}$ 1032 for ( i; 1 ~ @ ) { if ( i > 10 ) break; sout | i; } $\C{sout | nl;}$ 1033 for ( i; @ -~ 10 ) { if ( i < 0 ) break; sout | i; } $\C{sout | nl;}$ 1034 for ( i; 2 ~ @ ~ 2 ) { if ( i > 10 ) break; sout | i; } $\C{sout | nl;}$ 1035 for ( i; 2.1 ~ @ ~ @ ) { if ( i > 10.5 ) break; sout | i; i += 1.7; } $\C{sout | nl;}$ 1036 for ( i; @ -~ 10 ~ 2 ) { if ( i < 0 ) break; sout | i; } $\C{sout | nl;}$ 1037 for ( i; 12.1 ~ @ ~ @ ) { if ( i < 2.5 ) break; sout | i; i -= 1.7; } $\C{sout | nl;}$ 1038 for ( i; 5 : j; -5 ~ @ ) { sout | i | j; } $\C{sout | nl;}$ 1039 for ( i; 5 : j; @ -~ -5 ) { sout | i | j; } $\C{sout | nl;}$ 1040 for ( i; 5 : j; -5 ~ @ ~ 2 ) { sout | i | j; } $\C{sout | nl;}$ 1041 for ( i; 5 : j; @ -~ -5 ~ 2 ) { sout | i | j; } $\C{sout | nl;}$ 1042 for ( i; 5 : j; -5 ~ @ ) { sout | i | j; } $\C{sout | nl;}$ 1043 for ( i; 5 : j; @ -~ -5 ) { sout | i | j; } $\C{sout | nl;}$ 1044 for ( i; 5 : j; -5 ~ @ ~ 2 ) { sout | i | j; } $\C{sout | nl;}$ 1045 for ( i; 5 : j; @ -~ -5 ~ 2 ) { sout | i | j; } $\C{sout | nl;}$ 1046 for ( i; 5 : j; @ -~ -5 ~ 2 : k; 1.5 ~ @ ) { sout | i | j | k; } $\C{sout | nl;}$ 1047 for ( i; 5 : j; @ -~ -5 ~ 2 : k; 1.5 ~ @ ) { sout | i | j | k; } $\C{sout | nl;}$ 1048 for ( i; 5 : k; 1.5 ~ @ : j; @ -~ -5 ~ 2 ) { sout | i | j | k; } $\C{sout | nl;}\CRT$ 1048 1049 \end{cfa} 1049 1050 & … … 1116 1117 The \Indexc{for}, \Indexc{while}, and \Indexc{do} loop-control allow an empty conditional, which implies a comparison value of ©1© (true). 1117 1118 \begin{cfa} 1118 while ( ®/* empty */® ) §\C{// while ( true )}§1119 for ( ®/* empty */® ) §\C{// for ( ; true; )}§1120 do ... while ( ®/* empty */® ) §\C{// do ... while ( true )}§1119 while ( ®/* empty */® ) $\C{// while ( true )}$ 1120 for ( ®/* empty */® ) $\C{// for ( ; true; )}$ 1121 do ... while ( ®/* empty */® ) $\C{// do ... while ( true )}$ 1121 1122 \end{cfa} 1122 1123 … … 1148 1149 If no type is specified for the loop index, it is the type of the high value H (when the low value is implicit) or the low value L. 1149 1150 \begin{cfa} 1150 for ( ®5® ) §\C{// typeof(5) anonymous-index; 5 is high value}§1151 for ( i; ®1.5® ~ 5.5 ) §\C{// typeof(1.5) i; 1.5 is low value}§1152 for ( ®int i®; 0 ~ 10 ~ 2 ) §\C{// int i; type is explicit}§1151 for ( ®5® ) $\C{// typeof(5) anonymous-index; 5 is high value}$ 1152 for ( i; ®1.5® ~ 5.5 ) $\C{// typeof(1.5) i; 1.5 is low value}$ 1153 for ( ®int i®; 0 ~ 10 ~ 2 ) $\C{// int i; type is explicit}$ 1153 1154 \end{cfa} 1154 1155 … … 1158 1159 H is implicit up-to exclusive range [0,H\R{)}. 1159 1160 \begin{cfa} 1160 for ( ®5® ) §\C{// for ( typeof(5) i; i < 5; i += 1 )}§1161 for ( ®5® ) $\C{// for ( typeof(5) i; i < 5; i += 1 )}$ 1161 1162 \end{cfa} 1162 1163 \item 1163 1164 ©~=© H is implicit up-to inclusive range [0,H\R{]}. 1164 1165 \begin{cfa} 1165 for ( ®~=® 5 ) §\C{// for ( typeof(5) i; i <= 5; i += 1 )}§1166 for ( ®~=® 5 ) $\C{// for ( typeof(5) i; i <= 5; i += 1 )}$ 1166 1167 \end{cfa} 1167 1168 \item 1168 1169 L ©~©\index{~@©~©} H is explicit up-to exclusive range [L,H\R{)}. 1169 1170 \begin{cfa} 1170 for ( 1 ®~® 5 ) §\C{// for ( typeof(1) i = 1; i < 5; i += 1 )}§1171 for ( 1 ®~® 5 ) $\C{// for ( typeof(1) i = 1; i < 5; i += 1 )}$ 1171 1172 \end{cfa} 1172 1173 \item 1173 1174 L ©~=©\index{~=@©~=©} H is explicit up-to inclusive range [L,H\R{]}. 1174 1175 \begin{cfa} 1175 for ( 1 ®~=® 5 ) §\C{// for ( typeof(1) i = 1; i <= 5; i += 1 )}§1176 for ( 1 ®~=® 5 ) $\C{// for ( typeof(1) i = 1; i <= 5; i += 1 )}$ 1176 1177 \end{cfa} 1177 1178 \item 1178 1179 L ©-~©\index{-~@©-~©} H is explicit down-to exclusive range [H,L\R{)}, where L and H are implicitly interchanged to make the range down-to. 1179 1180 \begin{cfa} 1180 for ( 1 ®-~® 5 ) §\C{// for ( typeof(1) i = 5; i > 0; i -= 1 )}§1181 for ( 1 ®-~® 5 ) $\C{// for ( typeof(1) i = 5; i > 0; i -= 1 )}$ 1181 1182 \end{cfa} 1182 1183 \item 1183 1184 L ©-~=©\index{-~=@©-~=©} H is explicit down-to inclusive range [H,L\R{]}, where L and H are implicitly interchanged to make the range down-to. 1184 1185 \begin{cfa} 1185 for ( 1 ®-~=® 5 ) §\C{// for ( typeof(1) i = 5; i >= 0; i -= 1 )}§1186 for ( 1 ®-~=® 5 ) $\C{// for ( typeof(1) i = 5; i >= 0; i -= 1 )}$ 1186 1187 \end{cfa} 1187 1188 \item 1188 1189 ©@© means put nothing in this field. 1189 1190 \begin{cfa} 1190 for ( i; 1 ~ ®@® ~ 2 ) §\C{// for ( typeof(1) i = 1; \R{/* empty */}; i += 2 )}§1191 for ( i; 1 ~ 10 ~ ®@® ) §\C{// for ( typeof(1) i = 1; i < 10; \R{/* empty */} )}§1192 for ( i; 1 ~ ®@® ~ ®@® ) §\C{// for ( typeof(1) i = 1; /*empty*/; \R{/* empty */} )}§1191 for ( i; 1 ~ ®@® ~ 2 ) $\C{// for ( typeof(1) i = 1; \R{/* empty */}; i += 2 )}$ 1192 for ( i; 1 ~ 10 ~ ®@® ) $\C{// for ( typeof(1) i = 1; i < 10; \R{/* empty */} )}$ 1193 for ( i; 1 ~ ®@® ~ ®@® ) $\C{// for ( typeof(1) i = 1; /*empty*/; \R{/* empty */} )}$ 1193 1194 \end{cfa} 1194 1195 L cannot be elided for the up-to range, \lstinline{@ ~ 5}, and H for the down-to range, \lstinline{1 -~ @}, because then the loop index is uninitialized. … … 1197 1198 ©:© means low another index. 1198 1199 \begin{cfa} 1199 for ( i; 5 ®:® j; 2 ~ 12 ~ 3 ) §\C{// for ( typeof(i) i = 1, j = 2; i < 5 \&\& j < 12; i += 1, j += 3 )}§1200 for ( i; 5 ®:® j; 2 ~ 12 ~ 3 ) $\C{// for ( typeof(i) i = 1, j = 2; i < 5 \&\& j < 12; i += 1, j += 3 )}$ 1200 1201 \end{cfa} 1201 1202 \end{itemize} 1202 1203 \R{Warning}: specifying the down-to range maybe unexpected because the loop control \emph{implicitly} switches the L and H values (and toggles the increment/decrement for I): 1203 1204 \begin{cfa} 1204 for ( i; 1 ~ 10 ) §{\C{// up range}§1205 for ( i; 1 -~ 10 ) §{\C{// down range}§1206 for ( i; ®10 -~ 1® ) §{\C{// \R{WRONG down range!}}}§1205 for ( i; 1 ~ 10 ) ${\C{// up range}$ 1206 for ( i; 1 -~ 10 ) ${\C{// down range}$ 1207 for ( i; ®10 -~ 1® ) ${\C{// \R{WRONG down range!}}}$ 1207 1208 \end{cfa} 1208 1209 The reason for this semantics is that the range direction can be toggled by adding/removing the minus, ©'-'©, versus interchanging the L and H expressions, which has a greater chance of introducing errors. … … 1360 1361 Grouping heterogeneous data into an \newterm{aggregate} (structure/union) is a common programming practice, and aggregates may be nested: 1361 1362 \begin{cfa} 1362 struct Person { §\C{// aggregate}§1363 struct Name { §\C{// nesting}§1363 struct Person { $\C{// aggregate}$ 1364 struct Name { $\C{// nesting}$ 1364 1365 char first[20], last[20]; 1365 1366 } name; 1366 struct Address { §\C{// nesting}§1367 struct Address { $\C{// nesting}$ 1367 1368 ... 1368 1369 } address; … … 1373 1374 \begin{cfa} 1374 1375 Person p 1375 ®p.®name; ®p.®address; ®p.®sex; §\C{// access containing fields}§1376 ®p.®name; ®p.®address; ®p.®sex; $\C{// access containing fields}$ 1376 1377 \end{cfa} 1377 1378 which extends to multiple levels of qualification for nested aggregates and multiple aggregates. 1378 1379 \begin{cfa} 1379 1380 struct Ticket { ... } t; 1380 ®p.name®.first; ®p.address®.street; §\C{// access nested fields}§1381 ®t.®departure; ®t.®cost; §\C{// access multiple aggregate}§1381 ®p.name®.first; ®p.address®.street; $\C{// access nested fields}$ 1382 ®t.®departure; ®t.®cost; $\C{// access multiple aggregate}$ 1382 1383 \end{cfa} 1383 1384 Repeated aggregate qualification is tedious and makes code difficult to read. … … 1388 1389 \begin{cfa} 1389 1390 struct S { 1390 struct §\R{\LstCommentStyle{/* unnamed */}}§{ int g, h; } __attribute__(( aligned(64) ));1391 struct $\R{\LstCommentStyle{/* unnamed */}}$ { int g, h; } __attribute__(( aligned(64) )); 1391 1392 int tag; 1392 union §\R{\LstCommentStyle{/* unnamed */}}§{1393 union $\R{\LstCommentStyle{/* unnamed */}}$ { 1393 1394 struct { char c1, c2; } __attribute__(( aligned(128) )); 1394 1395 struct { int i1, i2; }; … … 1404 1405 struct S { 1405 1406 char ®c®; int ®i®; double ®d®; 1406 void f( /* S * this */ ) { §\C{// implicit ``this'' parameter}§1407 ®c®; ®i®; ®d®; §\C{// this->c; this->i; this->d;}§1407 void f( /* S * this */ ) { $\C{// implicit ``this'' parameter}$ 1408 ®c®; ®i®; ®d®; $\C{// this->c; this->i; this->d;}$ 1408 1409 } 1409 1410 } … … 1413 1414 \begin{cfa} 1414 1415 struct T { 1415 char ®m®; int ®i®; double ®n®; §\C{// derived class variables}§1416 char ®m®; int ®i®; double ®n®; $\C{// derived class variables}$ 1416 1417 }; 1417 1418 struct S : public T { 1418 char ®c®; int ®i®; double ®d®; §\C{// class variables}§1419 char ®c®; int ®i®; double ®d®; $\C{// class variables}$ 1419 1420 void g( double ®d®, T & t ) { 1420 d; ®t®.m; ®t®.i; ®t®.n; §\C{// function parameter}§1421 c; i; ®this->®d; ®S::®d; §\C{// class S variables}§1422 m; ®T::®i; n; §\C{// class T variables}§1421 d; ®t®.m; ®t®.i; ®t®.n; $\C{// function parameter}$ 1422 c; i; ®this->®d; ®S::®d; $\C{// class S variables}$ 1423 m; ®T::®i; n; $\C{// class T variables}$ 1423 1424 } 1424 1425 }; … … 1430 1431 Hence, the qualified fields become variables with the side-effect that it is simpler to write, easier to read, and optimize field references in a block. 1431 1432 \begin{cfa} 1432 void f( S & this ) ®with ( this )® { §\C{// with statement}§1433 ®c®; ®i®; ®d®; §\C{// this.c, this.i, this.d}§1433 void f( S & this ) ®with ( this )® { $\C{// with statement}$ 1434 ®c®; ®i®; ®d®; $\C{// this.c, this.i, this.d}$ 1434 1435 } 1435 1436 \end{cfa} 1436 1437 with the generality of opening multiple aggregate-parameters: 1437 1438 \begin{cfa} 1438 void g( S & s, T & t ) ®with ( s, t )® { §\C{// multiple aggregate parameters}§1439 c; ®s.®i; d; §\C{// s.c, s.i, s.d}§1440 m; ®t.®i; n; §\C{// t.m, t.i, t.n}§1439 void g( S & s, T & t ) ®with ( s, t )® {$\C{// multiple aggregate parameters}$ 1440 c; ®s.®i; d; $\C{// s.c, s.i, s.d}$ 1441 m; ®t.®i; n; $\C{// t.m, t.i, t.n}$ 1441 1442 } 1442 1443 \end{cfa} … … 1461 1462 struct R { int ®i®; int j; double ®m®; } r, w; 1462 1463 with ( r, q ) { 1463 j + k; §\C{// unambiguous, r.j + q.k}§1464 m = 5.0; §\C{// unambiguous, q.m = 5.0}§1465 m = 1; §\C{// unambiguous, r.m = 1}§1466 int a = m; §\C{// unambiguous, a = r.i }§1467 double b = m; §\C{// unambiguous, b = q.m}§1468 int c = r.i + q.i; §\C{// disambiguate with qualification}§1469 (double)m; §\C{// disambiguate with cast}§1464 j + k; $\C{// unambiguous, r.j + q.k}$ 1465 m = 5.0; $\C{// unambiguous, q.m = 5.0}$ 1466 m = 1; $\C{// unambiguous, r.m = 1}$ 1467 int a = m; $\C{// unambiguous, a = r.i }$ 1468 double b = m; $\C{// unambiguous, b = q.m}$ 1469 int c = r.i + q.i; $\C{// disambiguate with qualification}$ 1470 (double)m; $\C{// disambiguate with cast}$ 1470 1471 } 1471 1472 \end{cfa} … … 1475 1476 \begin{cfa} 1476 1477 with ( r ) { 1477 i; §\C{// unambiguous, r.i}§1478 i; $\C{// unambiguous, r.i}$ 1478 1479 with ( q ) { 1479 i; §\C{// unambiguous, q.i}§1480 i; $\C{// unambiguous, q.i}$ 1480 1481 } 1481 1482 } … … 1484 1485 A cast can also be used to disambiguate among overload variables in a ©with© \emph{expression}: 1485 1486 \begin{cfa} 1486 with ( w ) { ... } §\C{// ambiguous, same name and no context}§1487 with ( (Q)w ) { ... } §\C{// unambiguous, cast}§1487 with ( w ) { ... } $\C{// ambiguous, same name and no context}$ 1488 with ( (Q)w ) { ... } $\C{// unambiguous, cast}$ 1488 1489 \end{cfa} 1489 1490 Because there is no left-side in the ©with© expression to implicitly disambiguate between the ©w© variables, it is necessary to explicitly disambiguate by casting ©w© to type ©Q© or ©R©. … … 1492 1493 \begin{cfa} 1493 1494 void f( S & s, char c ) with ( s ) { 1494 ®s.c = c;® i = 3; d = 5.5; §\C{// initialize fields}§1495 ®s.c = c;® i = 3; d = 5.5; $\C{// initialize fields}$ 1495 1496 } 1496 1497 \end{cfa} … … 1498 1499 To solve this problem, parameters \emph{not} explicitly opened are treated like an initialized aggregate: 1499 1500 \begin{cfa} 1500 struct Params { §\C{// s explicitly opened so S \& s elided}§1501 struct Params { $\C{// s explicitly opened so S \& s elided}$ 1501 1502 char c; 1502 1503 } params; … … 1504 1505 and implicitly opened \emph{after} a function-body open, to give them higher priority: 1505 1506 \begin{cfa} 1506 void f( S & s, char ®c® ) with ( s ) ®with( §\emph{\R{params}}§)® { // syntax not allowed, illustration only1507 void f( S & s, char ®c® ) with ( s ) ®with( $\emph{\R{params}}$ )® { // syntax not allowed, illustration only 1507 1508 s.c = ®c;® i = 3; d = 5.5; 1508 1509 } … … 1537 1538 1538 1539 \begin{cfa} 1539 exception_t E {}; §\C{// exception type}§1540 exception_t E {}; $\C{// exception type}$ 1540 1541 void f(...) { 1541 ... throw E{}; ... §\C{// termination}§1542 ... throwResume E{}; ... §\C{// resumption}§1542 ... throw E{}; ... $\C{// termination}$ 1543 ... throwResume E{}; ... $\C{// resumption}$ 1543 1544 } 1544 1545 try { 1545 1546 f(...); 1546 } catch( E e ; §boolean-predicate§ ) { §\C{// termination handler}§1547 } catch( E e ; $boolean-predicate$ ) { $\C{// termination handler}$ 1547 1548 // recover and continue 1548 } catchResume( E e ; §boolean-predicate§ ) { §\C{// resumption handler}§1549 } catchResume( E e ; $boolean-predicate$ ) { $\C{// resumption handler}$ 1549 1550 // repair and return 1550 1551 } finally { … … 1623 1624 For example, a routine returning a \Index{pointer} to an array of integers is defined and used in the following way: 1624 1625 \begin{cfa} 1625 int ®(*®f®())[®5®]® {...}; §\C{// definition}§1626 ... ®(*®f®())[®3®]® += 1; §\C{// usage}§1626 int ®(*®f®())[®5®]® {...}; $\C{// definition}$ 1627 ... ®(*®f®())[®3®]® += 1; $\C{// usage}$ 1627 1628 \end{cfa} 1628 1629 Essentially, the return type is wrapped around the routine name in successive layers (like an \Index{onion}). … … 1869 1870 For example, \Index*{Algol68}~\cite{Algol68} infers pointer dereferencing to select the best meaning for each pointer usage 1870 1871 \begin{cfa} 1871 p2 = p1 + x; §\C{// compiler infers *p2 = *p1 + x;}§1872 p2 = p1 + x; $\C{// compiler infers *p2 = *p1 + x;}$ 1872 1873 \end{cfa} 1873 1874 Algol68 infers the following dereferencing ©*p2 = *p1 + x©, because adding the arbitrary integer value in ©x© to the address of ©p1© and storing the resulting address into ©p2© is an unlikely operation. … … 1877 1878 In C, objects of pointer type always manipulate the pointer object's address: 1878 1879 \begin{cfa} 1879 p1 = p2; §\C{// p1 = p2\ \ rather than\ \ *p1 = *p2}§1880 p2 = p1 + x; §\C{// p2 = p1 + x\ \ rather than\ \ *p2 = *p1 + x}§1880 p1 = p2; $\C{// p1 = p2\ \ rather than\ \ *p1 = *p2}$ 1881 p2 = p1 + x; $\C{// p2 = p1 + x\ \ rather than\ \ *p2 = *p1 + x}$ 1881 1882 \end{cfa} 1882 1883 even though the assignment to ©p2© is likely incorrect, and the programmer probably meant: 1883 1884 \begin{cfa} 1884 p1 = p2; §\C{// pointer address assignment}§1885 ®*®p2 = ®*®p1 + x; §\C{// pointed-to value assignment / operation}§1885 p1 = p2; $\C{// pointer address assignment}$ 1886 ®*®p2 = ®*®p1 + x; $\C{// pointed-to value assignment / operation}$ 1886 1887 \end{cfa} 1887 1888 The C semantics work well for situations where manipulation of addresses is the primary meaning and data is rarely accessed, such as storage management (©malloc©/©free©). … … 1900 1901 \begin{cfa} 1901 1902 int x, y, ®&® r1, ®&® r2, ®&&® r3; 1902 ®&®r1 = &x; §\C{// r1 points to x}§1903 ®&®r2 = &r1; §\C{// r2 points to x}§1904 ®&®r1 = &y; §\C{// r1 points to y}§1905 ®&&®r3 = ®&®&r2; §\C{// r3 points to r2}§1906 r2 = ((r1 + r2) * (r3 - r1)) / (r3 - 15); §\C{// implicit dereferencing}§1903 ®&®r1 = &x; $\C{// r1 points to x}$ 1904 ®&®r2 = &r1; $\C{// r2 points to x}$ 1905 ®&®r1 = &y; $\C{// r1 points to y}$ 1906 ®&&®r3 = ®&®&r2; $\C{// r3 points to r2}$ 1907 r2 = ((r1 + r2) * (r3 - r1)) / (r3 - 15); $\C{// implicit dereferencing}$ 1907 1908 \end{cfa} 1908 1909 Except for auto-dereferencing by the compiler, this reference example is the same as the previous pointer example. … … 1919 1920 For a \CFA reference type, the cancellation on the left-hand side of assignment leaves the reference as an address (\Index{lvalue}): 1920 1921 \begin{cfa} 1921 (&®*®)r1 = &x; §\C{// (\&*) cancel giving address in r1 not variable pointed-to by r1}§1922 (&®*®)r1 = &x; $\C{// (\&*) cancel giving address in r1 not variable pointed-to by r1}$ 1922 1923 \end{cfa} 1923 1924 Similarly, the address of a reference can be obtained for assignment or computation (\Index{rvalue}): 1924 1925 \begin{cfa} 1925 (&(&®*®)®*®)r3 = &(&®*®)r2; §\C{// (\&*) cancel giving address in r2, (\&(\&*)*) cancel giving address in r3}§1926 (&(&®*®)®*®)r3 = &(&®*®)r2; $\C{// (\&*) cancel giving address in r2, (\&(\&*)*) cancel giving address in r3}$ 1926 1927 \end{cfa} 1927 1928 Cancellation\index{cancellation!pointer/reference}\index{pointer!cancellation} works to arbitrary depth. … … 1931 1932 int x, *p1 = &x, **p2 = &p1, ***p3 = &p2, 1932 1933 &r1 = x, &&r2 = r1, &&&r3 = r2; 1933 ***p3 = 3; §\C{// change x}§1934 r3 = 3; §\C{// change x, ***r3}§1935 **p3 = ...; §\C{// change p1}§1936 &r3 = ...; §\C{// change r1, (\&*)**r3, 1 cancellation}§1937 *p3 = ...; §\C{// change p2}§1938 &&r3 = ...; §\C{// change r2, (\&(\&*)*)*r3, 2 cancellations}§1939 &&&r3 = p3; §\C{// change r3 to p3, (\&(\&(\&*)*)*)r3, 3 cancellations}§1934 ***p3 = 3; $\C{// change x}$ 1935 r3 = 3; $\C{// change x, ***r3}$ 1936 **p3 = ...; $\C{// change p1}$ 1937 &r3 = ...; $\C{// change r1, (\&*)**r3, 1 cancellation}$ 1938 *p3 = ...; $\C{// change p2}$ 1939 &&r3 = ...; $\C{// change r2, (\&(\&*)*)*r3, 2 cancellations}$ 1940 &&&r3 = p3; $\C{// change r3 to p3, (\&(\&(\&*)*)*)r3, 3 cancellations}$ 1940 1941 \end{cfa} 1941 1942 Furthermore, both types are equally performant, as the same amount of dereferencing occurs for both types. … … 1944 1945 As for a pointer type, a reference type may have qualifiers: 1945 1946 \begin{cfa} 1946 const int cx = 5; §\C{// cannot change cx;}§1947 const int & cr = cx; §\C{// cannot change what cr points to}§1948 ®&®cr = &cx; §\C{// can change cr}§1949 cr = 7; §\C{// error, cannot change cx}§1950 int & const rc = x; §\C{// must be initialized}§1951 ®&®rc = &x; §\C{// error, cannot change rc}§1952 const int & const crc = cx; §\C{// must be initialized}§1953 crc = 7; §\C{// error, cannot change cx}§1954 ®&®crc = &cx; §\C{// error, cannot change crc}§1947 const int cx = 5; $\C{// cannot change cx;}$ 1948 const int & cr = cx; $\C{// cannot change what cr points to}$ 1949 ®&®cr = &cx; $\C{// can change cr}$ 1950 cr = 7; $\C{// error, cannot change cx}$ 1951 int & const rc = x; $\C{// must be initialized}$ 1952 ®&®rc = &x; $\C{// error, cannot change rc}$ 1953 const int & const crc = cx; $\C{// must be initialized}$ 1954 crc = 7; $\C{// error, cannot change cx}$ 1955 ®&®crc = &cx; $\C{// error, cannot change crc}$ 1955 1956 \end{cfa} 1956 1957 Hence, for type ©& const©, there is no pointer assignment, so ©&rc = &x© is disallowed, and \emph{the address value cannot be the null pointer unless an arbitrary pointer is coerced\index{coercion} into the reference}: 1957 1958 \begin{cfa} 1958 int & const cr = *0; §\C{// where 0 is the int * zero}§1959 int & const cr = *0; $\C{// where 0 is the int * zero}$ 1959 1960 \end{cfa} 1960 1961 Note, constant reference-types do not prevent \Index{addressing errors} because of explicit storage-management: … … 1963 1964 cr = 5; 1964 1965 free( &cr ); 1965 cr = 7; §\C{// unsound pointer dereference}§1966 cr = 7; $\C{// unsound pointer dereference}$ 1966 1967 \end{cfa} 1967 1968 … … 1971 1972 \begin{cquote} 1972 1973 \begin{tabular}{@{}l@{\hspace{3em}}l@{}} 1973 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{C }} & \multicolumn{1}{c}{\textbf{\CFA}} \\1974 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{Cy}} & \multicolumn{1}{c}{\textbf{\CFA}} \\ 1974 1975 \begin{cfa} 1975 1976 const int * ®const® * ®const® ccp; … … 1987 1988 Finally, like pointers, references are usable and composable with other type operators and generators. 1988 1989 \begin{cfa} 1989 int w, x, y, z, & ar[3] = { x, y, z }; §\C{// initialize array of references}§1990 &ar[1] = &w; §\C{// change reference array element}§1991 typeof( ar[1] ) p; §\C{// (gcc) is int, \ie the type of referenced object}§1992 typeof( &ar[1] ) q; §\C{// (gcc) is int \&, \ie the type of reference}§1993 sizeof( ar[1] ) == sizeof( int ); §\C{// is true, \ie the size of referenced object}§1994 sizeof( &ar[1] ) == sizeof( int *) §\C{// is true, \ie the size of a reference}§1990 int w, x, y, z, & ar[3] = { x, y, z }; $\C{// initialize array of references}$ 1991 &ar[1] = &w; $\C{// change reference array element}$ 1992 typeof( ar[1] ) p; $\C{// (gcc) is int, \ie the type of referenced object}$ 1993 typeof( &ar[1] ) q; $\C{// (gcc) is int \&, \ie the type of reference}$ 1994 sizeof( ar[1] ) == sizeof( int ); $\C{// is true, \ie the size of referenced object}$ 1995 sizeof( &ar[1] ) == sizeof( int *) $\C{// is true, \ie the size of a reference}$ 1995 1996 \end{cfa} 1996 1997 … … 2009 2010 Therefore, for pointer/reference initialization, the initializing value must be an address not a value. 2010 2011 \begin{cfa} 2011 int * p = &x; §\C{// assign address of x}§2012 ®int * p = x;® §\C{// assign value of x}§2013 int & r = x; §\C{// must have address of x}§2012 int * p = &x; $\C{// assign address of x}$ 2013 ®int * p = x;® $\C{// assign value of x}$ 2014 int & r = x; $\C{// must have address of x}$ 2014 2015 \end{cfa} 2015 2016 Like the previous example with C pointer-arithmetic, it is unlikely assigning the value of ©x© into a pointer is meaningful (again, a warning is usually given). … … 2020 2021 Similarly, when a reference type is used for a parameter/return type, the call-site argument does not require a reference operator for the same reason. 2021 2022 \begin{cfa} 2022 int & f( int & r ); §\C{// reference parameter and return}§2023 z = f( x ) + f( y ); §\C{// reference operator added, temporaries needed for call results}§2023 int & f( int & r ); $\C{// reference parameter and return}$ 2024 z = f( x ) + f( y ); $\C{// reference operator added, temporaries needed for call results}$ 2024 2025 \end{cfa} 2025 2026 Within routine ©f©, it is possible to change the argument by changing the corresponding parameter, and parameter ©r© can be locally reassigned within ©f©. … … 2048 2049 void f( int & r ); 2049 2050 void g( int * p ); 2050 f( 3 ); g( ®&®3 ); §\C{// compiler implicit generates temporaries}§2051 f( x + y ); g( ®&®(x + y) ); §\C{// compiler implicit generates temporaries}§2051 f( 3 ); g( ®&®3 ); $\C{// compiler implicit generates temporaries}$ 2052 f( x + y ); g( ®&®(x + y) ); $\C{// compiler implicit generates temporaries}$ 2052 2053 \end{cfa} 2053 2054 Essentially, there is an implicit \Index{rvalue} to \Index{lvalue} conversion in this case.\footnote{ … … 2060 2061 \begin{cfa} 2061 2062 void f( int i ); 2062 void (* fp)( int ); §\C{// routine pointer}§2063 fp = f; §\C{// reference initialization}§2064 fp = &f; §\C{// pointer initialization}§2065 fp = *f; §\C{// reference initialization}§2066 fp(3); §\C{// reference invocation}§2067 (*fp)(3); §\C{// pointer invocation}§2063 void (* fp)( int ); $\C{// routine pointer}$ 2064 fp = f; $\C{// reference initialization}$ 2065 fp = &f; $\C{// pointer initialization}$ 2066 fp = *f; $\C{// reference initialization}$ 2067 fp(3); $\C{// reference invocation}$ 2068 (*fp)(3); $\C{// pointer invocation}$ 2068 2069 \end{cfa} 2069 2070 While C's treatment of routine objects has similarity to inferring a reference type in initialization contexts, the examples are assignment not initialization, and all possible forms of assignment are possible (©f©, ©&f©, ©*f©) without regard for type. 2070 2071 Instead, a routine object should be referenced by a ©const© reference: 2071 2072 \begin{cfa} 2072 ®const® void (®&® fr)( int ) = f; §\C{// routine reference}§2073 fr = ... ; §\C{// error, cannot change code}§2074 &fr = ...; §\C{// changing routine reference}§2075 fr( 3 ); §\C{// reference call to f}§2076 (*fr)(3); §\C{// error, incorrect type}§2073 ®const® void (®&® fr)( int ) = f; $\C{// routine reference}$ 2074 fr = ... $\C{// error, cannot change code}$ 2075 &fr = ...; $\C{// changing routine reference}$ 2076 fr( 3 ); $\C{// reference call to f}$ 2077 (*fr)(3); $\C{// error, incorrect type}$ 2077 2078 \end{cfa} 2078 2079 because the value of the routine object is a routine literal, \ie the routine code is normally immutable during execution.\footnote{ … … 2096 2097 int x, * px, ** ppx, *** pppx, **** ppppx; 2097 2098 int & rx = x, && rrx = rx, &&& rrrx = rrx ; 2098 x = rrrx; §\C{// rrrx is an lvalue with type int \&\&\& (equivalent to x)}§2099 px = &rrrx; §\C{// starting from rrrx, \&rrrx is an rvalue with type int *\&\&\& (\&x)}§2100 ppx = &&rrrx; §\C{// starting from \&rrrx, \&\&rrrx is an rvalue with type int **\&\& (\&rx)}§2101 pppx = &&&rrrx; §\C{// starting from \&\&rrrx, \&\&\&rrrx is an rvalue with type int ***\& (\&rrx)}§2102 ppppx = &&&&rrrx; §\C{// starting from \&\&\&rrrx, \&\&\&\&rrrx is an rvalue with type int **** (\&rrrx)}§2099 x = rrrx; $\C[2.0in]{// rrrx is an lvalue with type int \&\&\& (equivalent to x)}$ 2100 px = &rrrx; $\C{// starting from rrrx, \&rrrx is an rvalue with type int *\&\&\& (\&x)}$ 2101 ppx = &&rrrx; $\C{// starting from \&rrrx, \&\&rrrx is an rvalue with type int **\&\& (\&rx)}$ 2102 pppx = &&&rrrx; $\C{// starting from \&\&rrrx, \&\&\&rrrx is an rvalue with type int ***\& (\&rrx)}$ 2103 ppppx = &&&&rrrx; $\C{// starting from \&\&\&rrrx, \&\&\&\&rrrx is an rvalue with type int **** (\&rrrx)}$ 2103 2104 \end{cfa} 2104 2105 The following example shows the second rule applied to different \Index{lvalue} contexts: … … 2106 2107 int x, * px, ** ppx, *** pppx; 2107 2108 int & rx = x, && rrx = rx, &&& rrrx = rrx ; 2108 rrrx = 2; §\C{// rrrx is an lvalue with type int \&\&\& (equivalent to x)}§2109 &rrrx = px; §\C{// starting from rrrx, \&rrrx is an rvalue with type int *\&\&\& (rx)}§2110 &&rrrx = ppx; §\C{// starting from \&rrrx, \&\&rrrx is an rvalue with type int **\&\& (rrx)}§2111 &&&rrrx = pppx; §\C{// starting from \&\&rrrx, \&\&\&rrrx is an rvalue with type int ***\& (rrrx)}§2109 rrrx = 2; $\C{// rrrx is an lvalue with type int \&\&\& (equivalent to x)}$ 2110 &rrrx = px; $\C{// starting from rrrx, \&rrrx is an rvalue with type int *\&\&\& (rx)}$ 2111 &&rrrx = ppx; $\C{// starting from \&rrrx, \&\&rrrx is an rvalue with type int **\&\& (rrx)}$ 2112 &&&rrrx = pppx; $\C{// starting from \&\&rrrx, \&\&\&rrrx is an rvalue with type int ***\& (rrrx)}\CRT$ 2112 2113 \end{cfa} 2113 2114 … … 2122 2123 \begin{cfa} 2123 2124 int x; 2124 x + 1; §\C{// lvalue variable (int) converts to rvalue for expression}§2125 x + 1; $\C[2.0in]{// lvalue variable (int) converts to rvalue for expression}$ 2125 2126 \end{cfa} 2126 2127 An rvalue has no type qualifiers (©cv©), so the lvalue qualifiers are dropped. … … 2132 2133 \begin{cfa} 2133 2134 int x, &r = x, f( int p ); 2134 x = ®r® + f( ®r® ); §\C{// lvalue reference converts to rvalue}§2135 x = ®r® + f( ®r® ); $\C{// lvalue reference converts to rvalue}$ 2135 2136 \end{cfa} 2136 2137 An rvalue has no type qualifiers (©cv©), so the reference qualifiers are dropped. … … 2139 2140 lvalue to reference conversion: \lstinline[deletekeywords=lvalue]{lvalue-type cv1 T} converts to ©cv2 T &©, which allows implicitly converting variables to references. 2140 2141 \begin{cfa} 2141 int x, &r = ®x®, f( int & p ); §\C{// lvalue variable (int) convert to reference (int \&)}§2142 f( ®x® ); §\C{// lvalue variable (int) convert to reference (int \&)}§2142 int x, &r = ®x®, f( int & p ); $\C{// lvalue variable (int) convert to reference (int \&)}$ 2143 f( ®x® ); $\C{// lvalue variable (int) convert to reference (int \&)}\CRT$ 2143 2144 \end{cfa} 2144 2145 Conversion can restrict a type, where ©cv1© $\le$ ©cv2©, \eg passing an ©int© to a ©const volatile int &©, which has low cost. … … 2150 2151 \begin{cfa} 2151 2152 int x, & f( int & p ); 2152 f( ®x + 3® ); §\C{// rvalue parameter (int) implicitly converts to lvalue temporary reference (int \&)}§2153 ®&f®(...) = &x; §\C{// rvalue result (int \&) implicitly converts to lvalue temporary reference (int \&)}§2153 f( ®x + 3® ); $\C[1.5in]{// rvalue parameter (int) implicitly converts to lvalue temporary reference (int \&)}$ 2154 ®&f®(...) = &x; $\C{// rvalue result (int \&) implicitly converts to lvalue temporary reference (int \&)}\CRT$ 2154 2155 \end{cfa} 2155 2156 In both case, modifications to the temporary are inaccessible (\Index{warning}). … … 2318 2319 2319 2320 2320 \section{\lstinline{string} Type}2321 \label{s:stringType}2322 2323 The \CFA \Indexc{string} type is for manipulation of dynamically-size character-strings versus C \Indexc{char *} type for manipulation of statically-size null-terminated character-strings.2324 That is, the amount of storage for a \CFA string changes dynamically at runtime to fit the string size, whereas the amount of storage for a C string is fixed at compile time.2325 Hence, a ©string© declaration does not specify a maximum length;2326 as a string dynamically grows and shrinks in size, so does its underlying storage.2327 In contrast, a C string also dynamically grows and shrinks is size, but its underlying storage is fixed.2328 The maximum storage for a \CFA ©string© value is ©size_t© characters, which is $2^{32}$ or $2^{64}$ respectively.2329 A \CFA string manages its length separately from the string, so there is no null (©'\0'©) terminating value at the end of a string value.2330 Hence, a \CFA string cannot be passed to a C string manipulation routine, such as ©strcat©.2331 Like C strings, the characters in a ©string© are numbered starting from 0.2332 2333 The following operations have been defined to manipulate an instance of type ©string©.2334 The discussion assumes the following declarations and assignment statements are executed.2335 \begin{cfa}2336 #include ®<string.hfa>®2337 ®string® s, peter, digit, alpha, punctuation, ifstmt;2338 int i;2339 peter = "PETER";2340 digit = "0123456789";2341 punctuation = "().,";2342 ifstmt = "IF (A > B) {";2343 \end{cfa}2344 Note, the include file \Indexc{string.hfa} to access type ©string©.2345 2346 2347 \subsection{Implicit String Conversions}2348 2349 The types ©char©, ©char *©, ©int©, ©double©, ©_Complex©, including signness and different sizes, implicitly convert to type ©string©.2350 \VRef[Figure]{f:ImplicitStringConversions} shows examples of implicit conversion between C strings, integral, floating-point and complex types to ©string©2351 The implicit conversions can be specified explicitly, as in:2352 \begin{cfa}2353 s = string( "abc" ); // converts char * to string2354 s = string( 5 ); // converts int to string2355 s = string( 5.5 ); // converts double to string2356 \end{cfa}2357 Conversions from ©string© to ©char *© are supported but with restrictions.2358 Explicit As well, when a string is converted to a ©char *©, the storage for the ©char *© is created by the conversion operation, which must be subsequently deleted:2359 \begin{cfa}2360 string x = "abc";2361 char *p = x; // convert from string to char *2362 ...2363 delete p; // free storage created for p2364 \end{cfa}2365 2366 \begin{figure}2367 \begin{tabular}{@{}l@{\hspace{15pt}}|@{\hspace{15pt}}l@{}}2368 \begin{cfa}2369 // string s = 5; sout | s;2370 string s;2371 // conversion of char and char * to string2372 s = 'x'; §\CD{sout | s;}§2373 s = "abc"; §\CD{sout | s;}§2374 char cs[5] = "abc";2375 s = cs; §\CD{sout | s;}§2376 // conversion of integral, floating-point, and complex to string2377 s = 45hh; §\CD{sout | s;}§2378 s = 45h; §\CD{sout | s;}§2379 s = -(ssize_t)MAX - 1; §\CD{sout | s;}§2380 s = (size_t)MAX; §\CD{sout | s;}§2381 s = 5.5; §\CD{sout | s;}§2382 s = 5.5L; §\CD{sout | s;}§2383 s = 5.5+3.4i; §\CD{sout | s;}§2384 s = 5.5L+3.4Li; §\CD{sout | s;}§2385 // safe conversion from string to char *2386 strncpy( cs, s, sizeof(cs) ); §\CD{sout | cs;}§2387 char * cp = s; §\CD{sout | cp; // ownership}§2388 delete( cp );2389 cp = s + ' ' + s; §\CD{sout | cp; // ownership}§2390 delete( cp );2391 \end{cfa}2392 &2393 \begin{cfa}2394 2395 2396 2397 x2398 abc2399 2400 abc2401 2402 452403 452404 -92233720368547758082405 184467440737095516152406 5.52407 5.52408 5.5+3.4i2409 5.5+3.4i2410 2411 5.5+2412 5.5+3.4i2413 2414 5.5+3.4i 5.5+3.4i2415 2416 \end{cfa}2417 \end{tabular}2418 \caption{Implicit String Conversions}2419 \label{f:ImplicitStringConversions}2420 \end{figure}2421 2422 2423 \subsection{Comparison Operators}2424 2425 The binary relational and equality operators ©<©, ©<=©, ©>©, ©>=©, ©==©, ©!=© compare ©string© using lexicographical ordering, where longer strings are greater than shorter strings.2426 2427 2428 \subsection{Concatenation}2429 2430 The binary operator ©+© concatenates two strings.2431 \begin{cfa}2432 s = peter + digit; §\C{// s is assigned "PETER0123456789"}§2433 s += peter; §\C{// s is assigned "PETER0123456789PETER"}§2434 \end{cfa}2435 There is also an assignment form ©+=©.2436 2437 2438 \subsection{Repetition}2439 2440 The binary operator \Indexc{*} returns a string that is the string repeated ©n© times.2441 If ©n = 0©, a zero length string, ©""© is returned.2442 \begin{cfa}2443 s = (peter + ' ') * 3; §\C{// s is assigned "PETER PETER PETER"}§2444 \end{cfa}2445 There is also an assignment form ©*=©.2446 2447 2448 \subsection{Length}2449 2450 The ©length© operation2451 \begin{cfa}2452 int length()2453 \end{cfa}2454 returns the length of a string variable.2455 \begin{cfa}2456 i = peter.length(); §\C{// i is assigned the value 5}§2457 \end{cfa}2458 2459 2460 \subsection{Substring}2461 The substring operation:2462 \begin{cfa}2463 string operator () (int start, int lnth);2464 \end{cfa}2465 performs a substring operation that returns the string starting at a specified position (©start©) in the current string, and having the specified length (©lnth©).2466 A negative starting position is a specification from the right end of the string.2467 A negative length means that characters are selected in the opposite (right to left) direction from the starting position.2468 If the substring request extends beyond the beginning or end of the string, it is clipped (shortened) to the bounds of the string.2469 If the substring request is completely outside of the original string, a null string located at the end of the original string is returned.2470 \begin{cfa}2471 s = peter( 2, 3 ); §\C{// s is assigned "ETE"}§2472 s = peter( 4, -3 ); §\C{// s is assigned "ETE", length is opposite direction}§2473 s = peter( 2, 8 ); §\C{// s is assigned "ETER", length is clipped to 4}§2474 s = peter( 0, -1 ); §\C{// s is assigned "", beyond string so clipped to null}§2475 s = peter(-1, -1 ); §\C{// s is assigned "R", start and length are negative}§2476 \end{cfa}2477 The substring operation can also appear on the left hand side of the assignment operator.2478 The substring is replaced by the value on the right hand side of the assignment.2479 The length of the right-hand-side value may be shorter, the same length, or longer than the length of the substring that is selected on the left hand side of the assignment.2480 \begin{cfa}[mathescape=false]2481 digit( 3, 3 ) = ""; §\C{// digit is assigned "0156789"}§2482 digit( 4, 3 ) = "xyz"; §\C{// digit is assigned "015xyz9"}§2483 digit( 7, 0 ) = "***"; §\C{// digit is assigned "015xyz***9"}§2484 digit(-4, 3 ) = "$$$"; §\C{// digit is assigned "015xyz\$\$\$9"}§2485 \end{cfa}2486 A substring is treated as a pointer into the base (substringed) string rather than creating a copy of the subtext.2487 As with all pointers, if the item they are pointing at is changed, then the pointer is referring to the changed item.2488 Pointers to the result value of a substring operation are defined to always start at the same location in their base string as long as that starting location exists, independent of changes to themselves or the base string.2489 However, if the base string value changes, this may affect the values of one or more of the substrings to that base string.2490 If the base string value shortens so that its end is before the starting location of a substring, resulting in the substring starting location disappearing, the substring becomes a null string located at the end of the base string.2491 2492 The following example illustrates passing the results of substring operations by reference and by value to a subprogram.2493 Notice the side-effects to other reference parameters as one is modified.2494 \begin{cfa}2495 main() {2496 string x = "xxxxxxxxxxxxx";2497 test( x, x(1,3), x(3,3), x(5,5), x(9,5), x(9,5) );2498 }2499 2500 // x, a, b, c, & d are substring results passed by reference2501 // e is a substring result passed by value2502 void test(string &x, string &a, string &b, string &c, string &d, string e) {2503 §\C{// x a b c d e}§2504 a( 1, 2 ) = "aaa"; §\C{// aaaxxxxxxxxxxx aaax axx xxxxx xxxxx xxxxx}§2505 b( 2, 12 ) = "bbb"; §\C{// aaabbbxxxxxxxxx aaab abbb bbxxx xxxxx xxxxx}§2506 c( 4, 5 ) = "ccc"; §\C{// aaabbbxcccxxxxxx aaab abbb bbxccc ccxxx xxxxx}§2507 c = "yyy"; §\C{// aaabyyyxxxxxx aaab abyy yyy xxxxx xxxxx}§2508 d( 1, 3 ) = "ddd"; §\C{// aaabyyyxdddxx aaab abyy yyy dddxx xxxxx}§2509 e( 1, 3 ) = "eee"; §\C{// aaabyyyxdddxx aaab abyy yyy dddxx eeexx}§2510 x = e; §\C{// eeexx eeex exx x eeexx}§2511 }2512 \end{cfa}2513 2514 There is an assignment form of substring in which only the starting position is specified and the length is assumed to be the remainder of the string.2515 \begin{cfa}2516 string operator () (int start);2517 \end{cfa}2518 For example:2519 \begin{cfa}2520 s = peter( 2 ); §\C{// s is assigned "ETER"}§2521 peter( 2 ) = "IPER"; §\C{// peter is assigned "PIPER"}§2522 \end{cfa}2523 It is also possible to substring using a string as the index for selecting the substring portion of the string.2524 \begin{cfa}2525 string operator () (const string &index);2526 \end{cfa}2527 For example:2528 \begin{cfa}[mathescape=false]2529 digit( "xyz$$$" ) = "678"; §\C{// digit is assigned "0156789"}§2530 digit( "234") = "***"; §\C{// digit is assigned "0156789***"}§2531 \end{cfa}2532 %$2533 2534 2535 \subsection{Searching}2536 2537 The ©index© operation2538 \begin{cfa}2539 int index( const string &key, int start = 1, occurrence occ = first );2540 \end{cfa}2541 returns the position of the first or last occurrence of the ©key© (depending on the occurrence indicator ©occ© that is either ©first© or ©last©) in the current string starting the search at position ©start©.2542 If the ©key© does not appear in the current string, the length of the current string plus one is returned.2543 %If the ©key© has zero length, the value 1 is returned regardless of what the current string contains.2544 A negative starting position is a specification from the right end of the string.2545 \begin{cfa}2546 i = digit.index( "567" ); §\C{// i is assigned 3}§2547 i = digit.index( "567", 7 ); §\C{// i is assigned 11}§2548 i = digit.index( "567", -1, last ); §\C{// i is assigned 3}§2549 i = peter.index( "E", 5, last ); §\C{// i is assigned 4}§2550 \end{cfa}2551 2552 The next two string operations test a string to see if it is or is not composed completely of a particular class of characters.2553 For example, are the characters of a string all alphabetic or all numeric?2554 Use of these operations involves a two step operation.2555 First, it is necessary to create an instance of type ©strmask© and initialize it to a string containing the characters of the particular character class, as in:2556 \begin{cfa}2557 strmask digitmask = digit;2558 strmask alphamask = string( "abcdefghijklmnopqrstuvwxyz" );2559 \end{cfa}2560 Second, the character mask is used in the functions ©include© and ©exclude© to check a string for compliance of its characters with the characters indicated by the mask.2561 2562 The ©include© operation2563 \begin{cfa}2564 int include( const strmask &, int = 1, occurrence occ = first );2565 \end{cfa}2566 returns the position of the first or last character (depending on the occurrence indicator, which is either ©first© or ©last©) in the current string that does not appear in the ©mask© starting the search at position ©start©;2567 hence it skips over characters in the current string that are included (in) the ©mask©.2568 The characters in the current string do not have to be in the same order as the ©mask©.2569 If all the characters in the current string appear in the ©mask©, the length of the current string plus one is returned, regardless of which occurrence is being searched for.2570 A negative starting position is a specification from the right end of the string.2571 \begin{cfa}2572 i = peter.include( digitmask ); §\C{// i is assigned 1}§2573 i = peter.include( alphamask ); §\C{// i is assigned 6}§2574 \end{cfa}2575 2576 The ©exclude© operation2577 \begin{cfa}2578 int exclude( string &mask, int start = 1, occurrence occ = first )2579 \end{cfa}2580 returns the position of the first or last character (depending on the occurrence indicator, which is either ©first© or ©last©) in the current string that does appear in the ©mask© string starting the search at position ©start©;2581 hence it skips over characters in the current string that are excluded from (not in) in the ©mask© string.2582 The characters in the current string do not have to be in the same order as the ©mask© string.2583 If all the characters in the current string do NOT appear in the ©mask© string, the length of the current string plus one is returned, regardless of which occurrence is being searched for.2584 A negative starting position is a specification from the right end of the string.2585 \begin{cfa}2586 i = peter.exclude( digitmask ); §\C{// i is assigned 6}§2587 i = ifstmt.exclude( strmask( punctuation ) ); §\C{// i is assigned 4}§2588 \end{cfa}2589 2590 The ©includeStr© operation:2591 \begin{cfa}2592 string includeStr( strmask &mask, int start = 1, occurrence occ = first )2593 \end{cfa}2594 returns the longest substring of leading or trailing characters (depending on the occurrence indicator, which is either ©first© or ©last©) of the current string that ARE included in the ©mask© string starting the search at position ©start©.2595 A negative starting position is a specification from the right end of the string.2596 \begin{cfa}2597 s = peter.includeStr( alphamask ); §\C{// s is assigned "PETER"}§2598 s = ifstmt.includeStr( alphamask ); §\C{// s is assigned "IF"}§2599 s = peter.includeStr( digitmask ); §\C{// s is assigned ""}§2600 \end{cfa}2601 2602 The ©excludeStr© operation:2603 \begin{cfa}2604 string excludeStr( strmask &mask, int start = 1, occurrence = first )2605 \end{cfa}2606 returns the longest substring of leading or trailing characters (depending on the occurrence indicator, which is either ©first© or ©last©) of the current string that are excluded (NOT) in the ©mask© string starting the search at position ©start©.2607 A negative starting position is a specification from the right end of the string.2608 \begin{cfa}2609 s = peter.excludeStr( digitmask); §\C{// s is assigned "PETER"}§2610 s = ifstmt.excludeStr( strmask( punctuation ) ); §\C{// s is assigned "IF "}§2611 s = peter.excludeStr( alphamask); §\C{// s is assigned ""}§2612 \end{cfa}2613 2614 2615 \subsection{Miscellaneous}2616 2617 The ©trim© operation2618 \begin{cfa}2619 string trim( string &mask, occurrence occ = first )2620 \end{cfa}2621 returns a string in that is the longest substring of leading or trailing characters (depending on the occurrence indicator, which is either ©first© or ©last©) which ARE included in the ©mask© are removed.2622 \begin{cfa}2623 // remove leading blanks2624 s = string( " ABC" ).trim( " " ); §\C{// s is assigned "ABC",}§2625 // remove trailing blanks2626 s = string( "ABC " ).trim( " ", last ); §\C{// s is assigned "ABC",}§2627 \end{cfa}2628 2629 The ©translate© operation2630 \begin{cfa}2631 string translate( string &from, string &to )2632 \end{cfa}2633 returns a string that is the same length as the original string in which all occurrences of the characters that appear in the ©from© string have been translated into their corresponding character in the ©to© string.2634 Translation is done on a character by character basis between the ©from© and ©to© strings; hence these two strings must be the same length.2635 If a character in the original string does not appear in the ©from© string, then it simply appears as is in the resulting string.2636 \begin{cfa}2637 // upper to lower case2638 peter = peter.translate( "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz" );2639 // peter is assigned "peter"2640 s = ifstmt.translate( "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz" );2641 // ifstmt is assigned "if (a > b) {"2642 // lower to upper case2643 peter = peter.translate( "abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZ" );2644 // peter is assigned "PETER"2645 \end{cfa}2646 2647 The ©replace© operation2648 \begin{cfa}2649 string replace( string &from, string &to )2650 \end{cfa}2651 returns a string in which all occurrences of the ©from© string in the current string have been replaced by the ©to© string.2652 \begin{cfa}2653 s = peter.replace( "E", "XX" ); §\C{// s is assigned "PXXTXXR"}§2654 \end{cfa}2655 The replacement is done left-to-right.2656 When an instance of the ©from© string is found and changed to the ©to© string, it is NOT examined again for further replacement.2657 2658 2659 \section{Returning N+1 on Failure}2660 2661 Any of the string search routines can fail at some point during the search.2662 When this happens it is necessary to return indicating the failure.2663 Many string types in other languages use some special value to indicate the failure.2664 This value is often 0 or -1 (PL/I returns 0).2665 This section argues that a value of N+1, where N is the length of the base string in the search, is a more useful value to return.2666 The index-of function in APL returns N+1.2667 These are the boundary situations and are often overlooked when designing a string type.2668 2669 The situation that can be optimized by returning N+1 is when a search is performed to find the starting location for a substring operation.2670 For example, in a program that is extracting words from a text file, it is necessary to scan from left to right over whitespace until the first alphabetic character is found.2671 \begin{cfa}2672 line = line( line.exclude( alpha ) );2673 \end{cfa}2674 If a text line contains all whitespaces, the exclude operation fails to find an alphabetic character.2675 If ©exclude© returns 0 or -1, the result of the substring operation is unclear.2676 Most string types generate an error, or clip the starting value to 1, resulting in the entire whitespace string being selected.2677 If ©exclude© returns N+1, the starting position for the substring operation is beyond the end of the string leaving a null string.2678 2679 The same situation occurs when scanning off a word.2680 \begin{cfa}2681 start = line.include(alpha);2682 word = line(1, start - 1);2683 \end{cfa}2684 If the entire line is composed of a word, the include operation will fail to find a non-alphabetic character.2685 In general, returning 0 or -1 is not an appropriate starting position for the substring, which must substring off the word leaving a null string.2686 However, returning N+1 will substring off the word leaving a null string.2687 2688 2689 \subsection{Input/Output Operators}2690 2691 Both the \CC operators ©<<© and ©>>© are defined on type ©string©.2692 However, input of a string value is different from input of a ©char *© value.2693 When a string value is read, \emph{all} input characters from the current point in the input stream to either the end of line (©'\n'©) or the end of file are read.2694 2695 2696 2321 \section{Enumeration} 2697 2322 … … 2707 2332 Hence, enums may be overloaded with variable, enum, and function names. 2708 2333 \begin{cfa} 2709 int Foo; §\C{// type/variable separate namespaces}§2334 int Foo; $\C{// type/variable separate namespaces}$ 2710 2335 enum Foo { Bar }; 2711 enum Goo { Bar }; §\C[1.75in]{// overload Foo.Bar}§2712 double Bar; §\C{// overload Foo.Bar, Goo.Bar}\CRT§2336 enum Goo { Bar }; $\C[1.75in]{// overload Foo.Bar}$ 2337 double Bar; $\C{// overload Foo.Bar, Goo.Bar}\CRT$ 2713 2338 \end{cfa} 2714 2339 An anonymous enumeration injects enums with specific values into a scope. … … 2783 2408 The following examples illustrate the difference between the enumeration type and the type of its enums. 2784 2409 \begin{cfa} 2785 Math m = PI; §\C[1.5in]{// allowed}§2786 double d = PI; §\C{// allowed, conversion to base type}§2787 m = E; §\C{// allowed}§2788 m = Alph; §\C{// {\color{red}disallowed}}§2789 m = 3.141597; §\C{// {\color{red}disallowed}}§2790 d = m; §\C{// allowed}§2791 d = Alph; §\C{// {\color{red}disallowed}}§2792 Letter l = A; §\C{// allowed}§2793 Greek g = Alph; §\C{// allowed}§2794 l = Alph; §\C{// allowed, conversion to base type}§2795 g = A; §\C{// {\color{red}disallowed}}\CRT§2410 Math m = PI; $\C[1.5in]{// allowed}$ 2411 double d = PI; $\C{// allowed, conversion to base type}$ 2412 m = E; $\C{// allowed}$ 2413 m = Alph; $\C{// {\color{red}disallowed}}$ 2414 m = 3.141597; $\C{// {\color{red}disallowed}}$ 2415 d = m; $\C{// allowed}$ 2416 d = Alph; $\C{// {\color{red}disallowed}}$ 2417 Letter l = A; $\C{// allowed}$ 2418 Greek g = Alph; $\C{// allowed}$ 2419 l = Alph; $\C{// allowed, conversion to base type}$ 2420 g = A; $\C{// {\color{red}disallowed}}\CRT$ 2796 2421 \end{cfa} 2797 2422 … … 2883 2508 \begin{cfa} 2884 2509 ®[ int o1, int o2, char o3 ]® f( int i1, char i2, char i3 ) { 2885 §\emph{routine body}§2510 $\emph{routine body}$ 2886 2511 } 2887 2512 \end{cfa} … … 2894 2519 Declaration qualifiers can only appear at the start of a routine definition, \eg: 2895 2520 \begin{cfa} 2896 ®extern® [ int x ] g( int y ) { §\,§}2521 ®extern® [ int x ] g( int y ) {$\,$} 2897 2522 \end{cfa} 2898 2523 Lastly, if there are no output parameters or input parameters, the brackets and/or parentheses must still be specified; 2899 2524 in both cases the type is assumed to be void as opposed to old style C defaults of int return type and unknown parameter types, respectively, as in: 2900 2525 \begin{cfa} 2901 [ §\,§] g(); §\C{// no input or output parameters}§2902 [ void ] g( void ); §\C{// no input or output parameters}§2526 [$\,$] g(); $\C{// no input or output parameters}$ 2527 [ void ] g( void ); $\C{// no input or output parameters}$ 2903 2528 \end{cfa} 2904 2529 … … 2918 2543 \begin{cfa} 2919 2544 typedef int foo; 2920 int f( int (* foo) ); §\C{// foo is redefined as a parameter name}§2545 int f( int (* foo) ); $\C{// foo is redefined as a parameter name}$ 2921 2546 \end{cfa} 2922 2547 The string ``©int (* foo)©'' declares a C-style named-parameter of type pointer to an integer (the parenthesis are superfluous), while the same string declares a \CFA style unnamed parameter of type routine returning integer with unnamed parameter of type pointer to foo. … … 2926 2551 C-style declarations can be used to declare parameters for \CFA style routine definitions, \eg: 2927 2552 \begin{cfa} 2928 [ int ] f( * int, int * ); §\C{// returns an integer, accepts 2 pointers to integers}§2929 [ * int, int * ] f( int ); §\C{// returns 2 pointers to integers, accepts an integer}§2553 [ int ] f( * int, int * ); $\C{// returns an integer, accepts 2 pointers to integers}$ 2554 [ * int, int * ] f( int ); $\C{// returns 2 pointers to integers, accepts an integer}$ 2930 2555 \end{cfa} 2931 2556 The reason for allowing both declaration styles in the new context is for backwards compatibility with existing preprocessor macros that generate C-style declaration-syntax, as in: 2932 2557 \begin{cfa} 2933 2558 #define ptoa( n, d ) int (*n)[ d ] 2934 int f( ptoa( p, 5 ) ) ... §\C{// expands to int f( int (*p)[ 5 ] )}§2935 [ int ] f( ptoa( p, 5 ) ) ... §\C{// expands to [ int ] f( int (*p)[ 5 ] )}§2559 int f( ptoa( p, 5 ) ) ... $\C{// expands to int f( int (*p)[ 5 ] )}$ 2560 [ int ] f( ptoa( p, 5 ) ) ... $\C{// expands to [ int ] f( int (*p)[ 5 ] )}$ 2936 2561 \end{cfa} 2937 2562 Again, programmers are highly encouraged to use one declaration form or the other, rather than mixing the forms. … … 2955 2580 int z; 2956 2581 ... x = 0; ... y = z; ... 2957 ®return;® §\C{// implicitly return x, y}§2582 ®return;® $\C{// implicitly return x, y}$ 2958 2583 } 2959 2584 \end{cfa} … … 2965 2590 [ int x, int y ] f() { 2966 2591 ... 2967 } §\C{// implicitly return x, y}§2592 } $\C{// implicitly return x, y}$ 2968 2593 \end{cfa} 2969 2594 In this case, the current values of ©x© and ©y© are returned to the calling routine just as if a ©return© had been encountered. … … 2974 2599 [ int x, int y ] f( int, x, int y ) { 2975 2600 ... 2976 } §\C{// implicitly return x, y}§2601 } $\C{// implicitly return x, y}$ 2977 2602 \end{cfa} 2978 2603 This notation allows the compiler to eliminate temporary variables in nested routine calls. 2979 2604 \begin{cfa} 2980 [ int x, int y ] f( int, x, int y ); §\C{// prototype declaration}§2605 [ int x, int y ] f( int, x, int y ); $\C{// prototype declaration}$ 2981 2606 int a, b; 2982 2607 [a, b] = f( f( f( a, b ) ) ); … … 2992 2617 as well, parameter names are optional, \eg: 2993 2618 \begin{cfa} 2994 [ int x ] f (); §\C{// returning int with no parameters}§2995 [ * int ] g (int y); §\C{// returning pointer to int with int parameter}§2996 [ ] h ( int, char ); §\C{// returning no result with int and char parameters}§2997 [ * int, int ] j ( int ); §\C{// returning pointer to int and int, with int parameter}§2619 [ int x ] f (); $\C{// returning int with no parameters}$ 2620 [ * int ] g (int y); $\C{// returning pointer to int with int parameter}$ 2621 [ ] h ( int, char ); $\C{// returning no result with int and char parameters}$ 2622 [ * int, int ] j ( int ); $\C{// returning pointer to int and int, with int parameter}$ 2998 2623 \end{cfa} 2999 2624 This syntax allows a prototype declaration to be created by cutting and pasting source text from the routine definition header (or vice versa). … … 3001 2626 \begin{cfa} 3002 2627 C : const double bar1(), bar2( int ), bar3( double ); 3003 §\CFA§: [const double] foo(), foo( int ), foo( double ) { return 3.0; }2628 $\CFA$: [const double] foo(), foo( int ), foo( double ) { return 3.0; } 3004 2629 \end{cfa} 3005 2630 \CFA allows the last routine in the list to define its body. … … 3016 2641 The syntax for pointers to \CFA routines specifies the pointer name on the right, \eg: 3017 2642 \begin{cfa} 3018 * [ int x ] () fp; §\C[2.25in]{// pointer to routine returning int with no parameters}§3019 * [ * int ] (int y) gp; §\C{// pointer to routine returning pointer to int with int parameter}§3020 * [ ] (int,char) hp; §\C{// pointer to routine returning no result with int and char parameters}§3021 * [ * int,int ] ( int ) jp; §\C{// pointer to routine returning pointer to int and int, with int parameter}\CRT§2643 * [ int x ] () fp; $\C[2.25in]{// pointer to routine returning int with no parameters}$ 2644 * [ * int ] (int y) gp; $\C{// pointer to routine returning pointer to int with int parameter}$ 2645 * [ ] (int,char) hp; $\C{// pointer to routine returning no result with int and char parameters}$ 2646 * [ * int,int ] ( int ) jp; $\C{// pointer to routine returning pointer to int and int, with int parameter}\CRT$ 3022 2647 \end{cfa} 3023 2648 While parameter names are optional, \emph{a routine name cannot be specified}; 3024 2649 for example, the following is incorrect: 3025 2650 \begin{cfa} 3026 * [ int x ] f () fp; §\C{// routine name "f" is not allowed}§2651 * [ int x ] f () fp; $\C{// routine name "f" is not allowed}$ 3027 2652 \end{cfa} 3028 2653 … … 3047 2672 whereas a named (keyword) call may be: 3048 2673 \begin{cfa} 3049 p( z : 3, x : 4, y : 7 ); §\C{// rewrite \(\Rightarrow\) p( 4, 7, 3 )}§2674 p( z : 3, x : 4, y : 7 ); $\C{// rewrite \(\Rightarrow\) p( 4, 7, 3 )}$ 3050 2675 \end{cfa} 3051 2676 Here the order of the arguments is unimportant, and the names of the parameters are used to associate argument values with the corresponding parameters. … … 3064 2689 For example, the following routine prototypes and definition are all valid. 3065 2690 \begin{cfa} 3066 void p( int, int, int ); §\C{// equivalent prototypes}§2691 void p( int, int, int ); $\C{// equivalent prototypes}$ 3067 2692 void p( int x, int y, int z ); 3068 2693 void p( int y, int x, int z ); 3069 2694 void p( int z, int y, int x ); 3070 void p( int q, int r, int s ) {} §\C{// match with this definition}§2695 void p( int q, int r, int s ) {} $\C{// match with this definition}$ 3071 2696 \end{cfa} 3072 2697 Forcing matching parameter names in routine prototypes with corresponding routine definitions is possible, but goes against a strong tradition in C programming. … … 3080 2705 int f( int x, double y ); 3081 2706 3082 f( j : 3, i : 4 ); §\C{// 1st f}§3083 f( x : 7, y : 8.1 ); §\C{// 2nd f}§3084 f( 4, 5 ); §\C{// ambiguous call}§2707 f( j : 3, i : 4 ); $\C{// 1st f}$ 2708 f( x : 7, y : 8.1 ); $\C{// 2nd f}$ 2709 f( 4, 5 ); $\C{// ambiguous call}$ 3085 2710 \end{cfa} 3086 2711 However, named arguments compound routine resolution in conjunction with conversions: 3087 2712 \begin{cfa} 3088 f( i : 3, 5.7 ); §\C{// ambiguous call ?}§2713 f( i : 3, 5.7 ); $\C{// ambiguous call ?}$ 3089 2714 \end{cfa} 3090 2715 Depending on the cost associated with named arguments, this call could be resolvable or ambiguous. … … 3100 2725 the allowable positional calls are: 3101 2726 \begin{cfa} 3102 p(); §\C{// rewrite \(\Rightarrow\) p( 1, 2, 3 )}§3103 p( 4 ); §\C{// rewrite \(\Rightarrow\) p( 4, 2, 3 )}§3104 p( 4, 4 ); §\C{// rewrite \(\Rightarrow\) p( 4, 4, 3 )}§3105 p( 4, 4, 4 ); §\C{// rewrite \(\Rightarrow\) p( 4, 4, 4 )}§2727 p(); $\C{// rewrite \(\Rightarrow\) p( 1, 2, 3 )}$ 2728 p( 4 ); $\C{// rewrite \(\Rightarrow\) p( 4, 2, 3 )}$ 2729 p( 4, 4 ); $\C{// rewrite \(\Rightarrow\) p( 4, 4, 3 )}$ 2730 p( 4, 4, 4 ); $\C{// rewrite \(\Rightarrow\) p( 4, 4, 4 )}$ 3106 2731 // empty arguments 3107 p( , 4, 4 ); §\C{// rewrite \(\Rightarrow\) p( 1, 4, 4 )}§3108 p( 4, , 4 ); §\C{// rewrite \(\Rightarrow\) p( 4, 2, 4 )}§3109 p( 4, 4, ); §\C{// rewrite \(\Rightarrow\) p( 4, 4, 3 )}§3110 p( 4, , ); §\C{// rewrite \(\Rightarrow\) p( 4, 2, 3 )}§3111 p( , 4, ); §\C{// rewrite \(\Rightarrow\) p( 1, 4, 3 )}§3112 p( , , 4 ); §\C{// rewrite \(\Rightarrow\) p( 1, 2, 4 )}§3113 p( , , ); §\C{// rewrite \(\Rightarrow\) p( 1, 2, 3 )}§2732 p( , 4, 4 ); $\C{// rewrite \(\Rightarrow\) p( 1, 4, 4 )}$ 2733 p( 4, , 4 ); $\C{// rewrite \(\Rightarrow\) p( 4, 2, 4 )}$ 2734 p( 4, 4, ); $\C{// rewrite \(\Rightarrow\) p( 4, 4, 3 )}$ 2735 p( 4, , ); $\C{// rewrite \(\Rightarrow\) p( 4, 2, 3 )}$ 2736 p( , 4, ); $\C{// rewrite \(\Rightarrow\) p( 1, 4, 3 )}$ 2737 p( , , 4 ); $\C{// rewrite \(\Rightarrow\) p( 1, 2, 4 )}$ 2738 p( , , ); $\C{// rewrite \(\Rightarrow\) p( 1, 2, 3 )}$ 3114 2739 \end{cfa} 3115 2740 Here the missing arguments are inserted from the default values in the parameter list. … … 3135 2760 Default values may only appear in a prototype versus definition context: 3136 2761 \begin{cfa} 3137 void p( int x, int y = 2, int z = 3 ); §\C{// prototype: allowed}§3138 void p( int, int = 2, int = 3 ); §\C{// prototype: allowed}§3139 void p( int x, int y = 2, int z = 3 ) {} §\C{// definition: not allowed}§2762 void p( int x, int y = 2, int z = 3 ); $\C{// prototype: allowed}$ 2763 void p( int, int = 2, int = 3 ); $\C{// prototype: allowed}$ 2764 void p( int x, int y = 2, int z = 3 ) {} $\C{// definition: not allowed}$ 3140 2765 \end{cfa} 3141 2766 The reason for this restriction is to allow separate compilation. … … 3152 2777 \begin{cfa} 3153 2778 p( int x, int y, int z, ... ); 3154 p( 1, 4, 5, 6, z : 3, y : 2 ); §\C{// assume p( /* positional */, ... , /* named */ );}§3155 p( 1, z : 3, y : 2, 4, 5, 6 ); §\C{// assume p( /* positional */, /* named */, ... );}§2779 p( 1, 4, 5, 6, z : 3, y : 2 ); $\C{// assume p( /* positional */, ... , /* named */ );}$ 2780 p( 1, z : 3, y : 2, 4, 5, 6 ); $\C{// assume p( /* positional */, /* named */, ... );}$ 3156 2781 \end{cfa} 3157 2782 In the first call, it is necessary for the programmer to conceptually rewrite the call, changing named arguments into positional, before knowing where the ellipse arguments begin. … … 3162 2787 \begin{cfa} 3163 2788 void p( int x, int y = 2, int z = 3... ); 3164 p( 1, 4, 5, 6, z : 3 ); §\C{// assume p( /* positional */, ... , /* named */ );}§3165 p( 1, z : 3, 4, 5, 6 ); §\C{// assume p( /* positional */, /* named */, ... );}§2789 p( 1, 4, 5, 6, z : 3 ); $\C{// assume p( /* positional */, ... , /* named */ );}$ 2790 p( 1, z : 3, 4, 5, 6 ); $\C{// assume p( /* positional */, /* named */, ... );}$ 3166 2791 \end{cfa} 3167 2792 The first call is an error because arguments 4 and 5 are actually positional not ellipse arguments; … … 3193 2818 Furthermore, overloading cannot handle accessing default arguments in the middle of a positional list, via a missing argument, such as: 3194 2819 \begin{cfa} 3195 p( 1, /* default */, 5 ); §\C{// rewrite \(\Rightarrow\) p( 1, 2, 5 )}§2820 p( 1, /* default */, 5 ); $\C{// rewrite \(\Rightarrow\) p( 1, 2, 5 )}$ 3196 2821 \end{cfa} 3197 2822 … … 3206 2831 \begin{cfa} 3207 2832 struct { 3208 int f1; §\C{// named field}§3209 int f2 : 4; §\C{// named field with bit field size}§3210 int : 3; §\C{// unnamed field for basic type with bit field size}§3211 int ; §\C{// disallowed, unnamed field}§3212 int *; §\C{// disallowed, unnamed field}§3213 int (*)( int ); §\C{// disallowed, unnamed field}§2833 int f1; $\C{// named field}$ 2834 int f2 : 4; $\C{// named field with bit field size}$ 2835 int : 3; $\C{// unnamed field for basic type with bit field size}$ 2836 int ; $\C{// disallowed, unnamed field}$ 2837 int *; $\C{// disallowed, unnamed field}$ 2838 int (*)( int ); $\C{// disallowed, unnamed field}$ 3214 2839 }; 3215 2840 \end{cfa} … … 3219 2844 \begin{cfa} 3220 2845 struct { 3221 int , , ; §\C{// 3 unnamed fields}§2846 int , , ; $\C{// 3 unnamed fields}$ 3222 2847 } 3223 2848 \end{cfa} … … 3313 2938 const unsigned int size = 5; 3314 2939 int ia[size]; 3315 ... §\C{// assign values to array ia}§3316 qsort( ia, size ); §\C{// sort ascending order using builtin ?<?}§2940 ... $\C{// assign values to array ia}$ 2941 qsort( ia, size ); $\C{// sort ascending order using builtin ?<?}$ 3317 2942 { 3318 ®int ?<?( int x, int y ) { return x > y; }® §\C{// nested routine}§3319 qsort( ia, size ); §\C{// sort descending order by local redefinition}§2943 ®int ?<?( int x, int y ) { return x > y; }® $\C{// nested routine}$ 2944 qsort( ia, size ); $\C{// sort descending order by local redefinition}$ 3320 2945 } 3321 2946 \end{cfa} … … 3325 2950 The following program in undefined in \CFA (and Indexc{gcc}) 3326 2951 \begin{cfa} 3327 [* [int]( int )] foo() { §\C{// int (* foo())( int )}§2952 [* [int]( int )] foo() { $\C{// int (* foo())( int )}$ 3328 2953 int ®i® = 7; 3329 2954 int bar( int p ) { 3330 ®i® += 1; §\C{// dependent on local variable}§2955 ®i® += 1; $\C{// dependent on local variable}$ 3331 2956 sout | ®i®; 3332 2957 } 3333 return bar; §\C{// undefined because of local dependence}§2958 return bar; $\C{// undefined because of local dependence}$ 3334 2959 } 3335 2960 int main() { 3336 * [int]( int ) fp = foo(); §\C{// int (* fp)( int )}§2961 * [int]( int ) fp = foo(); $\C{// int (* fp)( int )}$ 3337 2962 sout | fp( 3 ); 3338 2963 } … … 3347 2972 In C and \CFA, lists of elements appear in several contexts, such as the parameter list of a routine call. 3348 2973 \begin{cfa} 3349 f( ®2, x, 3 + i® ); §\C{// element list}§2974 f( ®2, x, 3 + i® ); $\C{// element list}$ 3350 2975 \end{cfa} 3351 2976 A list of elements is called a \newterm{tuple}, and is different from a \Index{comma expression}. … … 3362 2987 For example, consider C's \Indexc{div} function, which returns the quotient and remainder for a division of an integer value. 3363 2988 \begin{cfa} 3364 typedef struct { int quot, rem; } div_t; §\C[7cm]{// from include stdlib.h}§2989 typedef struct { int quot, rem; } div_t; $\C[7cm]{// from include stdlib.h}$ 3365 2990 div_t div( int num, int den ); 3366 div_t qr = div( 13, 5 ); §\C{// return quotient/remainder aggregate}§3367 printf( "%d %d\n", qr.quot, qr.rem ); §\C{// print quotient/remainder}§2991 div_t qr = div( 13, 5 ); $\C{// return quotient/remainder aggregate}$ 2992 printf( "%d %d\n", qr.quot, qr.rem ); $\C{// print quotient/remainder}$ 3368 2993 \end{cfa} 3369 2994 This approach requires a name for the return type and fields, where \Index{naming} is a common programming-language issue. … … 3375 3000 For example, consider C's \Indexc{modf} function, which returns the integral and fractional part of a floating value. 3376 3001 \begin{cfa} 3377 double modf( double x, double * i ); §\C{// from include math.h}§3378 double intp, frac = modf( 13.5, &intp ); §\C{// return integral and fractional components}§3379 printf( "%g %g\n", intp, frac ); §\C{// print integral/fractional components}§3002 double modf( double x, double * i ); $\C{// from include math.h}$ 3003 double intp, frac = modf( 13.5, &intp ); $\C{// return integral and fractional components}$ 3004 printf( "%g %g\n", intp, frac ); $\C{// print integral/fractional components}$ 3380 3005 \end{cfa} 3381 3006 This approach requires allocating storage for the return values, which complicates the call site with a sequence of variable declarations leading to the call. … … 3404 3029 When a function call is passed as an argument to another call, the best match of actual arguments to formal parameters is evaluated given all possible expression interpretations in the current scope. 3405 3030 \begin{cfa} 3406 void g( int, int ); §\C{// 1}§3407 void g( double, double ); §\C{// 2}§3408 g( div( 13, 5 ) ); §\C{// select 1}§3409 g( modf( 13.5 ) ); §\C{// select 2}§3031 void g( int, int ); $\C{// 1}$ 3032 void g( double, double ); $\C{// 2}$ 3033 g( div( 13, 5 ) ); $\C{// select 1}$ 3034 g( modf( 13.5 ) ); $\C{// select 2}$ 3410 3035 \end{cfa} 3411 3036 In this case, there are two overloaded ©g© routines. … … 3416 3041 The previous examples can be rewritten passing the multiple returned-values directly to the ©printf© function call. 3417 3042 \begin{cfa} 3418 [ int, int ] div( int x, int y ); §\C{// from include stdlib}§3419 printf( "%d %d\n", div( 13, 5 ) ); §\C{// print quotient/remainder}§3420 3421 [ double, double ] modf( double x ); §\C{// from include math}§3422 printf( "%g %g\n", modf( 13.5 ) ); §\C{// print integral/fractional components}§3043 [ int, int ] div( int x, int y ); $\C{// from include stdlib}$ 3044 printf( "%d %d\n", div( 13, 5 ) ); $\C{// print quotient/remainder}$ 3045 3046 [ double, double ] modf( double x ); $\C{// from include math}$ 3047 printf( "%g %g\n", modf( 13.5 ) ); $\C{// print integral/fractional components}$ 3423 3048 \end{cfa} 3424 3049 This approach provides the benefits of compile-time checking for appropriate return statements as in aggregation, but without the required verbosity of declaring a new named type. … … 3430 3055 \begin{cfa} 3431 3056 int quot, rem; 3432 [ quot, rem ] = div( 13, 5 ); §\C{// assign multiple variables}§3433 printf( "%d %d\n", quot, rem ); §\C{// print quotient/remainder}\CRT§3057 [ quot, rem ] = div( 13, 5 ); $\C{// assign multiple variables}$ 3058 printf( "%d %d\n", quot, rem ); $\C{// print quotient/remainder}\CRT$ 3434 3059 \end{cfa} 3435 3060 Here, the multiple return-values are matched in much the same way as passing multiple return-values to multiple parameters in a call. … … 3460 3085 In \CFA, it is possible to overcome this restriction by declaring a \newterm{tuple variable}. 3461 3086 \begin{cfa} 3462 [int, int] ®qr® = div( 13, 5 ); §\C{// initialize tuple variable}§3463 printf( "%d %d\n", ®qr® ); §\C{// print quotient/remainder}§3087 [int, int] ®qr® = div( 13, 5 ); $\C{// initialize tuple variable}$ 3088 printf( "%d %d\n", ®qr® ); $\C{// print quotient/remainder}$ 3464 3089 \end{cfa} 3465 3090 It is now possible to match the multiple return-values to a single variable, in much the same way as \Index{aggregation}. … … 3467 3092 One way to access the individual components of a tuple variable is with assignment. 3468 3093 \begin{cfa} 3469 [ quot, rem ] = qr; §\C{// assign multiple variables}§3094 [ quot, rem ] = qr; $\C{// assign multiple variables}$ 3470 3095 \end{cfa} 3471 3096 … … 3490 3115 [int, double] * p; 3491 3116 3492 int y = x.0; §\C{// access int component of x}§3493 y = f().1; §\C{// access int component of f}§3494 p->0 = 5; §\C{// access int component of tuple pointed-to by p}§3495 g( x.1, x.0 ); §\C{// rearrange x to pass to g}§3496 double z = [ x, f() ].0.1; §\C{// access second component of first component of tuple expression}§3117 int y = x.0; $\C{// access int component of x}$ 3118 y = f().1; $\C{// access int component of f}$ 3119 p->0 = 5; $\C{// access int component of tuple pointed-to by p}$ 3120 g( x.1, x.0 ); $\C{// rearrange x to pass to g}$ 3121 double z = [ x, f() ].0.1; $\C{// access second component of first component of tuple expression}$ 3497 3122 \end{cfa} 3498 3123 Tuple-index expressions can occur on any tuple-typed expression, including tuple-returning functions, square-bracketed tuple expressions, and other tuple-index expressions, provided the retrieved component is also a tuple. … … 3562 3187 double y; 3563 3188 [int, double] z; 3564 [y, x] = 3.14; §\C{// mass assignment}§3565 [x, y] = z; §\C{// multiple assignment}§3566 z = 10; §\C{// mass assignment}§3567 z = [x, y]; §\C{// multiple assignment}§3189 [y, x] = 3.14; $\C{// mass assignment}$ 3190 [x, y] = z; $\C{// multiple assignment}$ 3191 z = 10; $\C{// mass assignment}$ 3192 z = [x, y]; $\C{// multiple assignment}$ 3568 3193 \end{cfa} 3569 3194 Let $L_i$ for $i$ in $[0, n)$ represent each component of the flattened left side, $R_i$ represent each component of the flattened right side of a multiple assignment, and $R$ represent the right side of a mass assignment. … … 3573 3198 \begin{cfa} 3574 3199 [ int, int ] x, y, z; 3575 [ x, y ] = z; §\C{// multiple assignment, invalid 4 != 2}§3200 [ x, y ] = z; $\C{// multiple assignment, invalid 4 != 2}$ 3576 3201 \end{cfa} 3577 3202 Multiple assignment assigns $R_i$ to $L_i$ for each $i$. … … 3609 3234 double c, d; 3610 3235 [ void ] f( [ int, int ] ); 3611 f( [ c, a ] = [ b, d ] = 1.5 ); §\C{// assignments in parameter list}§3236 f( [ c, a ] = [ b, d ] = 1.5 ); $\C{// assignments in parameter list}$ 3612 3237 \end{cfa} 3613 3238 The tuple expression begins with a mass assignment of ©1.5© into ©[b, d]©, which assigns ©1.5© into ©b©, which is truncated to ©1©, and ©1.5© into ©d©, producing the tuple ©[1, 1.5]© as a result. … … 3622 3247 \begin{cfa} 3623 3248 struct S; 3624 void ?{}(S *); §\C{// (1)}§3625 void ?{}(S *, int); §\C{// (2)}§3626 void ?{}(S * double); §\C{// (3)}§3627 void ?{}(S *, S); §\C{// (4)}§3628 3629 [S, S] x = [3, 6.28]; §\C{// uses (2), (3), specialized constructors}§3630 [S, S] y; §\C{// uses (1), (1), default constructor}§3631 [S, S] z = x.0; §\C{// uses (4), (4), copy constructor}§3249 void ?{}(S *); $\C{// (1)}$ 3250 void ?{}(S *, int); $\C{// (2)}$ 3251 void ?{}(S * double); $\C{// (3)}$ 3252 void ?{}(S *, S); $\C{// (4)}$ 3253 3254 [S, S] x = [3, 6.28]; $\C{// uses (2), (3), specialized constructors}$ 3255 [S, S] y; $\C{// uses (1), (1), default constructor}$ 3256 [S, S] z = x.0; $\C{// uses (4), (4), copy constructor}$ 3632 3257 \end{cfa} 3633 3258 In this example, ©x© is initialized by the multiple constructor calls ©?{}(&x.0, 3)© and ©?{}(&x.1, 6.28)©, while ©y© is initialized by two default constructor calls ©?{}(&y.0)© and ©?{}(&y.1)©. … … 3670 3295 A member-access tuple may be used anywhere a tuple can be used, \eg: 3671 3296 \begin{cfa} 3672 s.[ y, z, x ] = [ 3, 3.2, 'x' ]; §\C{// equivalent to s.x = 'x', s.y = 3, s.z = 3.2}§3673 f( s.[ y, z ] ); §\C{// equivalent to f( s.y, s.z )}§3297 s.[ y, z, x ] = [ 3, 3.2, 'x' ]; $\C{// equivalent to s.x = 'x', s.y = 3, s.z = 3.2}$ 3298 f( s.[ y, z ] ); $\C{// equivalent to f( s.y, s.z )}$ 3674 3299 \end{cfa} 3675 3300 Note, the fields appearing in a record-field tuple may be specified in any order; … … 3681 3306 void f( double, long ); 3682 3307 3683 f( x.[ 0, 3 ] ); §\C{// f( x.0, x.3 )}§3684 x.[ 0, 1 ] = x.[ 1, 0 ]; §\C{// [ x.0, x.1 ] = [ x.1, x.0 ]}§3308 f( x.[ 0, 3 ] ); $\C{// f( x.0, x.3 )}$ 3309 x.[ 0, 1 ] = x.[ 1, 0 ]; $\C{// [ x.0, x.1 ] = [ x.1, x.0 ]}$ 3685 3310 [ long, int, long ] y = x.[ 2, 0, 2 ]; 3686 3311 \end{cfa} … … 3699 3324 \begin{cfa} 3700 3325 [ int, float, double ] f(); 3701 [ double, float ] x = f().[ 2, 1 ]; §\C{// f() called once}§3326 [ double, float ] x = f().[ 2, 1 ]; $\C{// f() called once}$ 3702 3327 \end{cfa} 3703 3328 … … 3712 3337 That is, a cast can be used to select the type of an expression when it is ambiguous, as in the call to an overloaded function. 3713 3338 \begin{cfa} 3714 int f(); §\C{// (1)}§3715 double f(); §\C{// (2)}§3716 3717 f(); §\C{// ambiguous - (1),(2) both equally viable}§3718 (int)f(); §\C{// choose (2)}§3339 int f(); $\C{// (1)}$ 3340 double f(); $\C{// (2)}$ 3341 3342 f(); $\C{// ambiguous - (1),(2) both equally viable}$ 3343 (int)f(); $\C{// choose (2)}$ 3719 3344 \end{cfa} 3720 3345 Since casting is a fundamental operation in \CFA, casts need to be given a meaningful interpretation in the context of tuples. … … 3724 3349 void g(); 3725 3350 3726 (void)f(); §\C{// valid, ignore results}§3727 (int)g(); §\C{// invalid, void cannot be converted to int}§3351 (void)f(); $\C{// valid, ignore results}$ 3352 (int)g(); $\C{// invalid, void cannot be converted to int}$ 3728 3353 3729 3354 struct A { int x; }; 3730 (struct A)f(); §\C{// invalid, int cannot be converted to A}§3355 (struct A)f(); $\C{// invalid, int cannot be converted to A}$ 3731 3356 \end{cfa} 3732 3357 In C, line 4 is a valid cast, which calls ©f© and discards its result. … … 3744 3369 [int, [int, int], int] g(); 3745 3370 3746 ([int, double])f(); §\C{// (1) valid}§3747 ([int, int, int])g(); §\C{// (2) valid}§3748 ([void, [int, int]])g(); §\C{// (3) valid}§3749 ([int, int, int, int])g(); §\C{// (4) invalid}§3750 ([int, [int, int, int]])g(); §\C{// (5) invalid}§3371 ([int, double])f(); $\C{// (1) valid}$ 3372 ([int, int, int])g(); $\C{// (2) valid}$ 3373 ([void, [int, int]])g(); $\C{// (3) valid}$ 3374 ([int, int, int, int])g(); $\C{// (4) invalid}$ 3375 ([int, [int, int, int]])g(); $\C{// (5) invalid}$ 3751 3376 \end{cfa} 3752 3377 … … 3808 3433 void f([int, int], int, int); 3809 3434 3810 f([0, 0], 0, 0); §\C{// no cost}§3811 f(0, 0, 0, 0); §\C{// cost for structuring}§3812 f([0, 0,], [0, 0]); §\C{// cost for flattening}§3813 f([0, 0, 0], 0); §\C{// cost for flattening and structuring}§3435 f([0, 0], 0, 0); $\C{// no cost}$ 3436 f(0, 0, 0, 0); $\C{// cost for structuring}$ 3437 f([0, 0,], [0, 0]); $\C{// cost for flattening}$ 3438 f([0, 0, 0], 0); $\C{// cost for flattening and structuring}$ 3814 3439 \end{cfa} 3815 3440 … … 3875 3500 [ unsigned int, char ] 3876 3501 [ double, double, double ] 3877 [ * int, int * ] §\C{// mix of CFA and ANSI}§3502 [ * int, int * ] $\C{// mix of CFA and ANSI}$ 3878 3503 [ * [ 5 ] int, * * char, * [ [ int, int ] ] (int, int) ] 3879 3504 \end{cfa} … … 3882 3507 Examples of declarations using tuple types are: 3883 3508 \begin{cfa} 3884 [ int, int ] x; §\C{// 2 element tuple, each element of type int}§3885 * [ char, char ] y; §\C{// pointer to a 2 element tuple}§3509 [ int, int ] x; $\C{// 2 element tuple, each element of type int}$ 3510 * [ char, char ] y; $\C{// pointer to a 2 element tuple}$ 3886 3511 [ [ int, int ] ] z ([ int, int ]); 3887 3512 \end{cfa} … … 3900 3525 [ int, int ] w1; 3901 3526 [ int, int, int ] w2; 3902 [ void ] f (int, int, int); §\C{// three input parameters of type int}§3903 [ void ] g ([ int, int, int ]); §\C{3 element tuple as input}§3527 [ void ] f (int, int, int); $\C{// three input parameters of type int}$ 3528 [ void ] g ([ int, int, int ]); $\C{3 element tuple as input}$ 3904 3529 f( [ 1, 2, 3 ] ); 3905 3530 f( w1, 3 ); … … 3982 3607 [ int, int, int, int ] w = [ 1, 2, 3, 4 ]; 3983 3608 int x = 5; 3984 [ x, w ] = [ w, x ]; §\C{// all four tuple coercions}§3609 [ x, w ] = [ w, x ]; $\C{// all four tuple coercions}$ 3985 3610 \end{cfa} 3986 3611 Starting on the right-hand tuple in the last assignment statement, w is opened, producing a tuple of four values; … … 4072 3697 both these examples produce indeterminate results: 4073 3698 \begin{cfa} 4074 f( x++, x++ ); §\C{// C routine call with side effects in arguments}§4075 [ v1, v2 ] = [ x++, x++ ]; §\C{// side effects in right-hand side of multiple assignment}§3699 f( x++, x++ ); $\C{// C routine call with side effects in arguments}$ 3700 [ v1, v2 ] = [ x++, x++ ]; $\C{// side effects in right-hand side of multiple assignment}$ 4076 3701 \end{cfa} 4077 3702 … … 4172 3797 \begin{cfa} 4173 3798 [int, [ int, int ] ] t1 = [ 1, [ 2, 3 ] ], t2 = [ 4, [ 5, 6 ] ]; 4174 sout | t1 | t2; §\C{// print tuples}§3799 sout | t1 | t2; $\C{// print tuples}$ 4175 3800 \end{cfa} 4176 3801 \begin{cfa}[showspaces=true,aboveskip=0pt] … … 4256 3881 4257 3882 int main( int argc, char * argv[] ) { 4258 ®ifstream® in = stdin; §\C{// copy default files}§3883 ®ifstream® in = stdin; $\C{// copy default files}$ 4259 3884 ®ofstream® out = stdout; 4260 3885 … … 4262 3887 choose ( argc ) { 4263 3888 case 2, 3: 4264 ®open®( in, argv[1] ); §\C{// open input file first as output creates file}§4265 if ( argc == 3 ) ®open®( out, argv[2] ); §\C{// do not create output unless input opens}§4266 case 1: ; §\C{// use default files}§3889 ®open®( in, argv[1] ); $\C{// open input file first as output creates file}$ 3890 if ( argc == 3 ) ®open®( out, argv[2] ); $\C{// do not create output unless input opens}$ 3891 case 1: ; $\C{// use default files}$ 4267 3892 default: 4268 3893 ®exit® | "Usage" | argv[0] | "[ input-file (default stdin) " 4269 3894 "[ output-file (default stdout) ] ]"; 4270 3895 } // choose 4271 } catch( ®open_failure® * ex; ex->istream == &in ) { §\C{// input file errors}§3896 } catch( ®open_failure® * ex; ex->istream == &in ) { $\C{// input file errors}$ 4272 3897 ®exit® | "Unable to open input file" | argv[1]; 4273 } catch( ®open_failure® * ex; ex->ostream == &out ) { §\C{// output file errors}§4274 ®close®( in ); §\C{// optional}§3898 } catch( ®open_failure® * ex; ex->ostream == &out ) { $\C{// output file errors}$ 3899 ®close®( in ); $\C{// optional}$ 4275 3900 ®exit® | "Unable to open output file" | argv[2]; 4276 3901 } // try 4277 3902 4278 out | nlOff; §\C{// turn off auto newline}§4279 in | nlOn; §\C{// turn on reading newline}§3903 out | nlOff; $\C{// turn off auto newline}$ 3904 in | nlOn; $\C{// turn on reading newline}$ 4280 3905 char ch; 4281 for () { §\C{// read/write characters}§3906 for () { $\C{// read/write characters}$ 4282 3907 in | ch; 4283 if ( eof( in ) ) break; §\C{// eof ?}§3908 if ( eof( in ) ) break; $\C{// eof ?}$ 4284 3909 out | ch; 4285 3910 } // for … … 4328 3953 // *********************************** ofstream *********************************** 4329 3954 4330 bool fail( ofstream & ); §\indexc{fail}\index{ofstream@©ofstream©!©fail©}§4331 void clear( ofstream & ); §\indexc{clear}\index{ofstream@©ofstream©!©clear©}§4332 int flush( ofstream & ); §\indexc{flush}\index{ofstream@©ofstream©!©flush©}§4333 void open( ofstream &, const char name[], const char mode[] = "w" ); §\indexc{open}\index{ofstream@©ofstream©!©open©}§4334 void close( ofstream & ); §\indexc{close}\index{ofstream@©ofstream©!©close©}§4335 ofstream & write( ofstream &, const char data[], size_t size ); §\indexc{write}\index{ofstream@©ofstream©!©write©}§4336 4337 void ?{}( ofstream & ); §\index{ofstream@©ofstream©!©?{}©}§3955 bool fail( ofstream & );$\indexc{fail}\index{ofstream@©ofstream©!©fail©}$ 3956 void clear( ofstream & );$\indexc{clear}\index{ofstream@©ofstream©!©clear©}$ 3957 int flush( ofstream & );$\indexc{flush}\index{ofstream@©ofstream©!©flush©}$ 3958 void open( ofstream &, const char name[], const char mode[] = "w" );$\indexc{open}\index{ofstream@©ofstream©!©open©}$ 3959 void close( ofstream & );$\indexc{close}\index{ofstream@©ofstream©!©close©}$ 3960 ofstream & write( ofstream &, const char data[], size_t size );$\indexc{write}\index{ofstream@©ofstream©!©write©}$ 3961 3962 void ?{}( ofstream & );$\index{ofstream@©ofstream©!©?{}©}$ 4338 3963 void ?{}( ofstream &, const char name[], const char mode[] = "w" ); 4339 void ^?{}( ofstream & ); §\index{ofstream@©ofstream©!©^?{}©}§3964 void ^?{}( ofstream & );$\index{ofstream@©ofstream©!©^?{}©}$ 4340 3965 4341 3966 // *********************************** ifstream *********************************** 4342 3967 4343 bool fail( ifstream & is ); §\indexc{fail}\index{ifstream@©ifstream©!©fail©}§4344 void clear( ifstream & ); §\indexc{clear}\index{ifstream@©ifstream©!©clear©}§4345 bool eof( ifstream & is ); §\indexc{eof}\index{ifstream@©ifstream©!©eof©}§4346 void open( ifstream & is, const char name[], const char mode[] = "r" ); §\indexc{open}\index{ifstream@©ifstream©!©open©}§4347 void close( ifstream & is ); §\indexc{close}\index{ifstream@©ifstream©!©close©}§4348 ifstream & read( ifstream & is, char data[], size_t size ); §\indexc{read}\index{ifstream@©ifstream©!©read©}§4349 ifstream & ungetc( ifstream & is, char c ); §\indexc{unget}\index{ifstream@©ifstream©!©unget©}§4350 4351 void ?{}( ifstream & is ); §\index{ifstream@©ifstream©!©?{}©}§3968 bool fail( ifstream & is );$\indexc{fail}\index{ifstream@©ifstream©!©fail©}$ 3969 void clear( ifstream & );$\indexc{clear}\index{ifstream@©ifstream©!©clear©}$ 3970 bool eof( ifstream & is );$\indexc{eof}\index{ifstream@©ifstream©!©eof©}$ 3971 void open( ifstream & is, const char name[], const char mode[] = "r" );$\indexc{open}\index{ifstream@©ifstream©!©open©}$ 3972 void close( ifstream & is );$\indexc{close}\index{ifstream@©ifstream©!©close©}$ 3973 ifstream & read( ifstream & is, char data[], size_t size );$\indexc{read}\index{ifstream@©ifstream©!©read©}$ 3974 ifstream & ungetc( ifstream & is, char c );$\indexc{unget}\index{ifstream@©ifstream©!©unget©}$ 3975 3976 void ?{}( ifstream & is );$\index{ifstream@©ifstream©!©?{}©}$ 4352 3977 void ?{}( ifstream & is, const char name[], const char mode[] = "r" ); 4353 void ^?{}( ifstream & is ); §\index{ifstream@©ifstream©!©^?{}©}§3978 void ^?{}( ifstream & is );$\index{ifstream@©ifstream©!©^?{}©}$ 4354 3979 \end{cfa} 4355 3980 \caption{Stream Functions} … … 4438 4063 The separator string can be at most 16 characters including the ©'\0'© string terminator (15 printable characters). 4439 4064 \begin{cfa}[belowskip=0pt] 4440 sepSet( sout, ", $\LstStringStyle{\textdollar}$" ); §\C{// set separator from " " to ", \$"}§4065 sepSet( sout, ", $\LstStringStyle{\textdollar}$" ); $\C{// set separator from " " to ", \$"}$ 4441 4066 sout | 1 | 2 | 3 | " \"" | ®sepVal® | "\""; 4442 4067 \end{cfa} … … 4445 4070 \end{cfa} 4446 4071 \begin{cfa}[belowskip=0pt] 4447 sepSet( sout, " " ); §\C{// reset separator to " "}§4072 sepSet( sout, " " ); $\C{// reset separator to " "}$ 4448 4073 sout | 1 | 2 | 3 | " \"" | ®sepGet( sout )® | "\""; 4449 4074 \end{cfa} … … 4453 4078 ©sepGet© can be used to store a separator and then restore it: 4454 4079 \begin{cfa}[belowskip=0pt] 4455 char store[®sepSize®]; §\C{// sepSize is the maximum separator size}§4456 strcpy( store, sepGet( sout ) ); §\C{// copy current separator}§4457 sepSet( sout, "_" ); §\C{// change separator to underscore}§4080 char store[®sepSize®]; $\C{// sepSize is the maximum separator size}$ 4081 strcpy( store, sepGet( sout ) ); $\C{// copy current separator}$ 4082 sepSet( sout, "_" ); $\C{// change separator to underscore}$ 4458 4083 sout | 1 | 2 | 3; 4459 4084 \end{cfa} … … 4462 4087 \end{cfa} 4463 4088 \begin{cfa}[belowskip=0pt] 4464 sepSet( sout, store ); §\C{// change separator back to original}§4089 sepSet( sout, store ); $\C{// change separator back to original}$ 4465 4090 sout | 1 | 2 | 3; 4466 4091 \end{cfa} … … 4473 4098 The tuple separator-string can be at most 16 characters including the ©'\0'© string terminator (15 printable characters). 4474 4099 \begin{cfa}[belowskip=0pt] 4475 sepSetTuple( sout, " " ); §\C{// set tuple separator from ", " to " "}§4100 sepSetTuple( sout, " " ); $\C{// set tuple separator from ", " to " "}$ 4476 4101 sout | t1 | t2 | " \"" | ®sepTupleVal® | "\""; 4477 4102 \end{cfa} … … 4480 4105 \end{cfa} 4481 4106 \begin{cfa}[belowskip=0pt] 4482 sepSetTuple( sout, ", " ); §\C{// reset tuple separator to ", "}§4107 sepSetTuple( sout, ", " ); $\C{// reset tuple separator to ", "}$ 4483 4108 sout | t1 | t2 | " \"" | ®sepGetTuple( sout )® | "\""; 4484 4109 \end{cfa} … … 4491 4116 \Indexc{sepOff}\index{manipulator!sepOff@©sepOff©} and \Indexc{sepOn}\index{manipulator!sepOn@©sepOn©} globally toggle printing the separator. 4492 4117 \begin{cfa}[belowskip=0pt] 4493 sout | ®sepOff® | 1 | 2 | 3; §\C{// turn off implicit separator}§4118 sout | ®sepOff® | 1 | 2 | 3; $\C{// turn off implicit separator}$ 4494 4119 \end{cfa} 4495 4120 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] … … 4497 4122 \end{cfa} 4498 4123 \begin{cfa}[belowskip=0pt] 4499 sout | ®sepOn® | 1 | 2 | 3; §\C{// turn on implicit separator}§4124 sout | ®sepOn® | 1 | 2 | 3; $\C{// turn on implicit separator}$ 4500 4125 \end{cfa} 4501 4126 \begin{cfa}[mathescape=off,showspaces=true,aboveskip=0pt,belowskip=0pt] … … 4506 4131 \Indexc{sep}\index{manipulator!sep@©sep©} and \Indexc{nosep}\index{manipulator!nosep@©nosep©} locally toggle printing the separator with respect to the next printed item, and then return to the global separator setting. 4507 4132 \begin{cfa}[belowskip=0pt] 4508 sout | 1 | ®nosep® | 2 | 3; §\C{// turn off implicit separator for the next item}§4133 sout | 1 | ®nosep® | 2 | 3; $\C{// turn off implicit separator for the next item}$ 4509 4134 \end{cfa} 4510 4135 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] … … 4512 4137 \end{cfa} 4513 4138 \begin{cfa}[belowskip=0pt] 4514 sout | sepOff | 1 | ®sep® | 2 | 3; §\C{// turn on implicit separator for the next item}§4139 sout | sepOff | 1 | ®sep® | 2 | 3; $\C{// turn on implicit separator for the next item}$ 4515 4140 \end{cfa} 4516 4141 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] … … 4519 4144 The tuple separator also responses to being turned on and off. 4520 4145 \begin{cfa}[belowskip=0pt] 4521 sout | t1 | ®nosep® | t2; §\C{// turn off implicit separator for the next item}§4146 sout | t1 | ®nosep® | t2; $\C{// turn off implicit separator for the next item}$ 4522 4147 \end{cfa} 4523 4148 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] … … 4527 4152 Use ©sep© to accomplish this functionality. 4528 4153 \begin{cfa}[belowskip=0pt] 4529 sout | ®sep® | 1 | 2 | 3 | ®sep®; §\C{// sep does nothing at start/end of line}§4154 sout | ®sep® | 1 | 2 | 3 | ®sep®; $\C{// sep does nothing at start/end of line}$ 4530 4155 \end{cfa} 4531 4156 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] … … 4533 4158 \end{cfa} 4534 4159 \begin{cfa}[belowskip=0pt] 4535 sout | ®sepVal® | 1 | 2 | 3 | ®sepVal® ; §\C{// use sepVal to print separator at start/end of line}§4160 sout | ®sepVal® | 1 | 2 | 3 | ®sepVal® ; $\C{// use sepVal to print separator at start/end of line}$ 4536 4161 \end{cfa} 4537 4162 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] … … 4572 4197 \Indexc{nl}\index{manipulator!nl@©nl©} inserts a newline. 4573 4198 \begin{cfa} 4574 sout | ®nl®; §\C{// only print newline}§4575 sout | 2; §\C{// implicit newline}§4576 sout | 3 | ®nl® | 4 | ®nl®; §\C{// terminating nl merged with implicit newline}§4577 sout | 5 | ®nl® | ®nl®; §\C{// again terminating nl merged with implicit newline}§4578 sout | 6; §\C{// implicit newline}§4199 sout | ®nl®; $\C{// only print newline}$ 4200 sout | 2; $\C{// implicit newline}$ 4201 sout | 3 | ®nl® | 4 | ®nl®; $\C{// terminating nl merged with implicit newline}$ 4202 sout | 5 | ®nl® | ®nl®; $\C{// again terminating nl merged with implicit newline}$ 4203 sout | 6; $\C{// implicit newline}$ 4579 4204 4580 4205 2 … … 5023 4648 ®mutex( sout )® { 5024 4649 sout | 1; 5025 ®mutex( sout ) sout® | 2 | 3; §\C{// unnecessary, but ok because of recursive lock}§4650 ®mutex( sout ) sout® | 2 | 3; $\C{// unnecessary, but ok because of recursive lock}$ 5026 4651 sout | 4; 5027 4652 } // implicitly release sout lock … … 5035 4660 int x, y, z, w; 5036 4661 sin | x; 5037 ®mutex( sin )® sin | y | z; §\C{// unnecessary, but ok because of recursive lock}§4662 ®mutex( sin )® sin | y | z; $\C{// unnecessary, but ok because of recursive lock}$ 5038 4663 sin | w; 5039 4664 } // implicitly release sin lock … … 5044 4669 \Textbf{WARNING:} The general problem of \Index{nested locking} can occur if routines are called in an I/O sequence that block, \eg: 5045 4670 \begin{cfa} 5046 ®mutex( sout )® sout | "data:" | rtn( mon ); §\C{// mutex call on monitor}§4671 ®mutex( sout )® sout | "data:" | rtn( mon ); $\C{// mutex call on monitor}$ 5047 4672 \end{cfa} 5048 4673 If the thread executing the I/O expression blocks in the monitor with the ©sout© lock, other threads writing to ©sout© also block until the thread holding the lock is unblocked and releases it. … … 5062 4687 \begin{cfa} 5063 4688 12®,®345®.®123 $\C[1.25in]{// comma separator, period decimal-point}$ 5064 12®.®345®,®123 §\C{// period separator, comma decimal-point}§5065 12$\Sp$345®,®123®.® §\C{// space separator, comma decimal-point, period terminator}\CRT§4689 12®.®345®,®123 $\C{// period separator, comma decimal-point}$ 4690 12$\Sp$345®,®123®.® $\C{// space separator, comma decimal-point, period terminator}\CRT$ 5066 4691 \end{cfa} 5067 4692 A locale is selected with function ©setlocale©, and the corresponding locale package \emph{must} be installed on the underlying system; … … 5074 4699 \begin{cfa} 5075 4700 #include <fstream.hfa> 5076 #include <locale.h> §\C{// setlocale}§5077 #include <stdlib.h> §\C{// getenv}§4701 #include <locale.h> $\C{// setlocale}$ 4702 #include <stdlib.h> $\C{// getenv}$ 5078 4703 5079 4704 int main() { … … 5147 4772 int main() { 5148 4773 enum { size = 256 }; 5149 char buf[size]; §\C{// output buffer}§5150 ®ostrstream osstr = { buf, size };® §\C{// bind output buffer/size}§4774 char buf[size]; $\C{// output buffer}$ 4775 ®ostrstream osstr = { buf, size };® $\C{// bind output buffer/size}$ 5151 4776 int i = 3, j = 5, k = 7; 5152 4777 double x = 12345678.9, y = 98765.4321e-11; 5153 4778 5154 4779 osstr | i | hex(j) | wd(10, k) | sci(x) | unit(eng(y)) | "abc"; 5155 write( osstr ); §\C{// write string to stdout}§5156 printf( "%s", buf ); §\C{// same lines of output}§4780 write( osstr ); $\C{// write string to stdout}$ 4781 printf( "%s", buf ); $\C{// same lines of output}$ 5157 4782 sout | i | hex(j) | wd(10, k) | sci(x) | unit(eng(y)) | "abc"; 5158 4783 5159 char buf2[] = "12 14 15 3.5 7e4 abc"; §\C{// input buffer}§4784 char buf2[] = "12 14 15 3.5 7e4 abc"; $\C{// input buffer}$ 5160 4785 ®istrstream isstr = { buf2 };® 5161 4786 char s[10]; … … 5309 4934 // Subsequent arguments can be specified for initialization 5310 4935 5311 void ?{}( Widget & w ) { §\C{// default constructor}§4936 void ?{}( Widget & w ) { $\C{// default constructor}$ 5312 4937 w.id = -1; 5313 4938 w.size = 0.0; … … 5323 4948 5324 4949 // ^?{} is the destructor operator identifier 5325 void ^?{}( Widget & w ) { §\C{// destructor}§4950 void ^?{}( Widget & w ) { $\C{// destructor}$ 5326 4951 w.id = 0; 5327 4952 w.size = 0.0; … … 5332 4957 } 5333 4958 5334 Widget baz; §\C{// reserve space only}§5335 Widget foo{}; §\C{// calls default constructor}§5336 Widget bar{ 23, 2.45 }; §\C{// calls constructor with values}§5337 baz{ 24, 0.91 }; §\C{// calls constructor with values}§5338 ?{}( baz, 24, 0.91 ); §\C{// explicit call to constructor}§5339 ^?{} (bar ); §\C{// explicit call to destructor}§4959 Widget baz; $\C{// reserve space only}$ 4960 Widget foo{}; $\C{// calls default constructor}$ 4961 Widget bar{ 23, 2.45 }; $\C{// calls constructor with values}$ 4962 baz{ 24, 0.91 }; $\C{// calls constructor with values}$ 4963 ?{}( baz, 24, 0.91 ); $\C{// explicit call to constructor}$ 4964 ^?{} (bar ); $\C{// explicit call to destructor}$ 5340 4965 \end{cfa} 5341 4966 \caption{Constructors and Destructors} … … 5855 5480 5856 5481 ®coroutine® Fibonacci { 5857 int fn; §\C{// used for communication}§5482 int fn; $\C{// used for communication}$ 5858 5483 }; 5859 5484 5860 void main( Fibonacci & fib ) with( fib ) { §\C{// called on first resume}§5861 int fn1, fn2; §\C{// retained between resumes}§5862 fn = 0; fn1 = fn; §\C{// 1st case}§5863 ®suspend;® §\C{// restart last resume}§5864 fn = 1; fn2 = fn1; fn1 = fn; §\C{// 2nd case}§5865 ®suspend;® §\C{// restart last resume}§5485 void main( Fibonacci & fib ) with( fib ) { $\C{// called on first resume}$ 5486 int fn1, fn2; $\C{// retained between resumes}$ 5487 fn = 0; fn1 = fn; $\C{// 1st case}$ 5488 ®suspend;® $\C{// restart last resume}$ 5489 fn = 1; fn2 = fn1; fn1 = fn; $\C{// 2nd case}$ 5490 ®suspend;® $\C{// restart last resume}$ 5866 5491 for () { 5867 fn = fn1 + fn2; fn2 = fn1; fn1 = fn; §\C{// general case}§5868 ®suspend;® §\C{// restart last resume}§5492 fn = fn1 + fn2; fn2 = fn1; fn1 = fn; $\C{// general case}$ 5493 ®suspend;® $\C{// restart last resume}$ 5869 5494 } 5870 5495 } 5871 5496 int next( Fibonacci & fib ) with( fib ) { 5872 ®resume( fib );® §\C{// restart last suspend}§5497 ®resume( fib );® $\C{// restart last suspend}$ 5873 5498 return fn; 5874 5499 } 5875 5500 int main() { 5876 5501 Fibonacci f1, f2; 5877 for ( 10 ) { §\C{// print N Fibonacci values}§5502 for ( 10 ) { $\C{// print N Fibonacci values}$ 5878 5503 sout | next( f1 ) | next( f2 ); 5879 5504 } … … 5913 5538 int inc( AtomicCnt & ®mutex® c, int inc = 1 ) with(c) { return counter += inc; } 5914 5539 int dec( AtomicCnt & ®mutex® c, int dec = 1 ) with(c) { return counter -= dec; } 5915 forall( ostype & | ostream( ostype ) ) { §\C{// print any stream}§5540 forall( ostype & | ostream( ostype ) ) { $\C{// print any stream}$ 5916 5541 ostype & ?|?( ostype & os, AtomicCnt c ) { return os | c.counter; } 5917 5542 void ?|?( ostype & os, AtomicCnt c ) { (ostype &)(os | c.counter); ends( os ); } 5918 5543 } 5919 5544 5920 AtomicCnt global; §\C{// shared}§5545 AtomicCnt global; $\C{// shared}$ 5921 5546 5922 5547 thread MyThread {}; … … 5929 5554 int main() { 5930 5555 enum { Threads = 4 }; 5931 processor p[Threads - 1]; §\C{// + starting processor}§5556 processor p[Threads - 1]; $\C{// + starting processor}$ 5932 5557 { 5933 5558 MyThread t[Threads]; 5934 5559 } 5935 sout | global; §\C{// print 0}§5560 sout | global; $\C{// print 0}$ 5936 5561 } 5937 5562 \end{cfa} … … 7406 7031 In \CFA, there are ambiguous cases with dereference and operator identifiers, \eg ©int *?*?()©, where the string ©*?*?© can be interpreted as: 7407 7032 \begin{cfa} 7408 *?$\Sp$*? §\C{// dereference operator, dereference operator}§7409 *$\Sp$?*? §\C{// dereference, multiplication operator}§7033 *?$\Sp$*? $\C{// dereference operator, dereference operator}$ 7034 *$\Sp$?*? $\C{// dereference, multiplication operator}$ 7410 7035 \end{cfa} 7411 7036 By default, the first interpretation is selected, which does not yield a meaningful parse. … … 7459 7084 \eg: 7460 7085 \begin{cfa} 7461 x; §\C{// int x}§7462 *y; §\C{// int *y}§7463 f( p1, p2 ); §\C{// int f( int p1, int p2 );}§7464 g( p1, p2 ) int p1, p2; §\C{// int g( int p1, int p2 );}§7086 x; $\C{// int x}$ 7087 *y; $\C{// int *y}$ 7088 f( p1, p2 ); $\C{// int f( int p1, int p2 );}$ 7089 g( p1, p2 ) int p1, p2; $\C{// int g( int p1, int p2 );}$ 7465 7090 \end{cfa} 7466 7091 \CFA continues to support K\&R routine definitions: 7467 7092 \begin{cfa} 7468 f( a, b, c ) §\C{// default int return}§7469 int a, b; char c §\C{// K\&R parameter declarations}§7093 f( a, b, c ) $\C{// default int return}$ 7094 int a, b; char c $\C{// K\&R parameter declarations}$ 7470 7095 { 7471 7096 ... … … 7486 7111 int rtn( int i ); 7487 7112 int rtn( char c ); 7488 rtn( 'x' ); §\C{// programmer expects 2nd rtn to be called}§7113 rtn( 'x' ); $\C{// programmer expects 2nd rtn to be called}$ 7489 7114 \end{cfa} 7490 7115 \item[Rationale:] it is more intuitive for the call to ©rtn© to match the second version of definition of ©rtn© rather than the first. … … 7508 7133 \item[Change:] make string literals ©const©: 7509 7134 \begin{cfa} 7510 char * p = "abc"; §\C{// valid in C, deprecated in \CFA}§7511 char * q = expr ? "abc" : "de"; §\C{// valid in C, invalid in \CFA}§7135 char * p = "abc"; $\C{// valid in C, deprecated in \CFA}$ 7136 char * q = expr ? "abc" : "de"; $\C{// valid in C, invalid in \CFA}$ 7512 7137 \end{cfa} 7513 7138 The type of a string literal is changed from ©[] char© to ©const [] char©. … … 7516 7141 \begin{cfa} 7517 7142 char * p = "abc"; 7518 p[0] = 'w'; §\C{// segment fault or change constant literal}§7143 p[0] = 'w'; $\C{// segment fault or change constant literal}$ 7519 7144 \end{cfa} 7520 7145 The same problem occurs when passing a string literal to a routine that changes its argument. … … 7528 7153 \item[Change:] remove \newterm{tentative definitions}, which only occurs at file scope: 7529 7154 \begin{cfa} 7530 int i; §\C{// forward definition}§7531 int *j = ®&i®; §\C{// forward reference, valid in C, invalid in \CFA}§7532 int i = 0; §\C{// definition}§7155 int i; $\C{// forward definition}$ 7156 int *j = ®&i®; $\C{// forward reference, valid in C, invalid in \CFA}$ 7157 int i = 0; $\C{// definition}$ 7533 7158 \end{cfa} 7534 7159 is valid in C, and invalid in \CFA because duplicate overloaded object definitions at the same scope level are disallowed. … … 7536 7161 \begin{cfa} 7537 7162 struct X { int i; struct X *next; }; 7538 static struct X a; §\C{// forward definition}§7539 static struct X b = { 0, ®&a® }; §\C{// forward reference, valid in C, invalid in \CFA}§7540 static struct X a = { 1, &b }; §\C{// definition}§7163 static struct X a; $\C{// forward definition}$ 7164 static struct X b = { 0, ®&a® };$\C{// forward reference, valid in C, invalid in \CFA}$ 7165 static struct X a = { 1, &b }; $\C{// definition}$ 7541 7166 \end{cfa} 7542 7167 \item[Rationale:] avoids having different initialization rules for builtin types and user-defined types. … … 7553 7178 struct Person { 7554 7179 enum ®Colour® { R, G, B }; $\C[7cm]{// nested type}$ 7555 struct Face { §\C{// nested type}§7556 ®Colour® Eyes, Hair; §\C{// type defined outside (1 level)}§7180 struct Face { $\C{// nested type}$ 7181 ®Colour® Eyes, Hair; $\C{// type defined outside (1 level)}$ 7557 7182 }; 7558 ®.Colour® shirt; §\C{// type defined outside (top level)}§7559 ®Colour® pants; §\C{// type defined same level}§7560 Face looks[10]; §\C{// type defined same level}§7183 ®.Colour® shirt; $\C{// type defined outside (top level)}$ 7184 ®Colour® pants; $\C{// type defined same level}$ 7185 Face looks[10]; $\C{// type defined same level}$ 7561 7186 }; 7562 ®Colour® c = R; §\C{// type/enum defined same level}§7563 Person®.Colour® pc = Person®.®R; §\C{// type/enum defined inside}§7564 Person®.®Face pretty; §\C{// type defined inside}\CRT§7187 ®Colour® c = R; $\C{// type/enum defined same level}$ 7188 Person®.Colour® pc = Person®.®R;$\C{// type/enum defined inside}$ 7189 Person®.®Face pretty; $\C{// type defined inside}\CRT$ 7565 7190 \end{cfa} 7566 7191 In C, the name of the nested types belongs to the same scope as the name of the outermost enclosing structure, \ie the nested types are hoisted to the scope of the outer-most type, which is not useful and confusing. … … 7579 7204 \item[Difficulty of converting:] Semantic transformation. To make the struct type name visible in the scope of the enclosing struct, the struct tag could be declared in the scope of the enclosing struct, before the enclosing struct is defined. Example: 7580 7205 \begin{cfa} 7581 struct Y; §\C{// struct Y and struct X are at the same scope}§7206 struct Y; $\C{// struct Y and struct X are at the same scope}$ 7582 7207 struct X { 7583 7208 struct Y { /* ... */ } y; … … 7594 7219 \begin{cfa} 7595 7220 void foo() { 7596 int * b = malloc( sizeof(int) ); §\C{// implicitly convert void * to int *}§7597 char * c = b; §\C{// implicitly convert int * to void *, and then void * to char *}§7221 int * b = malloc( sizeof(int) ); $\C{// implicitly convert void * to int *}$ 7222 char * c = b; $\C{// implicitly convert int * to void *, and then void * to char *}$ 7598 7223 } 7599 7224 \end{cfa} … … 7837 7462 Type-safe allocation is provided for all C allocation routines and new \CFA allocation routines, \eg in 7838 7463 \begin{cfa} 7839 int * ip = (int *)malloc( sizeof(int) ); §\C{// C}§7840 int * ip = malloc(); §\C{// \CFA type-safe version of C malloc}§7841 int * ip = alloc(); §\C{// \CFA type-safe uniform alloc}§7464 int * ip = (int *)malloc( sizeof(int) ); $\C{// C}$ 7465 int * ip = malloc(); $\C{// \CFA type-safe version of C malloc}$ 7466 int * ip = alloc(); $\C{// \CFA type-safe uniform alloc}$ 7842 7467 \end{cfa} 7843 7468 the latter two allocations determine the allocation size from the type of ©p© (©int©) and cast the pointer to the allocated storage to ©int *©. … … 7846 7471 \begin{cfa} 7847 7472 struct S { int i; } __attribute__(( aligned( 128 ) )); // cache-line alignment 7848 S * sp = malloc(); §\C{// honour type alignment}§7473 S * sp = malloc(); $\C{// honour type alignment}$ 7849 7474 \end{cfa} 7850 7475 the storage allocation is implicitly aligned to 128 rather than the default 16. … … 7861 7486 \CFA memory management extends allocation to support constructors for initialization of allocated storage, \eg in 7862 7487 \begin{cfa} 7863 struct S { int i; }; §\C{// cache-line alignment}§7488 struct S { int i; }; $\C{// cache-line alignment}$ 7864 7489 void ?{}( S & s, int i ) { s.i = i; } 7865 7490 // assume ?|? operator for printing an S 7866 7491 7867 S & sp = *®new®( 3 ); §\C{// call constructor after allocation}§7492 S & sp = *®new®( 3 ); $\C{// call constructor after allocation}$ 7868 7493 sout | sp.i; 7869 7494 ®delete®( &sp ); 7870 7495 7871 S * spa = ®anew®( 10, 5 ); §\C{// allocate array and initialize each array element}§7496 S * spa = ®anew®( 10, 5 ); $\C{// allocate array and initialize each array element}$ 7872 7497 for ( i; 10 ) sout | spa[i] | nonl; 7873 7498 sout | nl; … … 7908 7533 // $\CFA$ safe general allocation, fill, resize, alignment, array 7909 7534 T * alloc( void );$\indexc{alloc}$ $\C[3.5in]{// variable, T size}$ 7910 T * alloc( size_t dim ); §\C{// array[dim], T size elements}§7911 T * alloc( T ptr[], size_t dim ); §\C{// realloc array[dim], T size elements}§7912 7913 T * alloc_set( char fill );$\indexc{alloc_set}$ §\C{// variable, T size, fill bytes with value}§7914 T * alloc_set( T fill ); §\C{// variable, T size, fill with value}§7915 T * alloc_set( size_t dim, char fill ); §\C{// array[dim], T size elements, fill bytes with value}§7916 T * alloc_set( size_t dim, T fill ); §\C{// array[dim], T size elements, fill elements with value}§7917 T * alloc_set( size_t dim, const T fill[] ); §\C{// array[dim], T size elements, fill elements with array}§7918 T * alloc_set( T ptr[], size_t dim, char fill ); §\C{// realloc array[dim], T size elements, fill bytes with value}§7919 7920 T * alloc_align( size_t align ); §\C{// aligned variable, T size}§7921 T * alloc_align( size_t align, size_t dim ); §\C{// aligned array[dim], T size elements}§7922 T * alloc_align( T ptr[], size_t align ); §\C{// realloc new aligned array}§7923 T * alloc_align( T ptr[], size_t align, size_t dim ); §\C{// realloc new aligned array[dim]}§7924 7925 T * alloc_align_set( size_t align, char fill ); §\C{// aligned variable, T size, fill bytes with value}§7926 T * alloc_align_set( size_t align, T fill ); §\C{// aligned variable, T size, fill with value}§7927 T * alloc_align_set( size_t align, size_t dim, char fill ); §\C{// aligned array[dim], T size elements, fill bytes with value}§7928 T * alloc_align_set( size_t align, size_t dim, T fill ); §\C{// aligned array[dim], T size elements, fill elements with value}§7929 T * alloc_align_set( size_t align, size_t dim, const T fill[] ); §\C{// aligned array[dim], T size elements, fill elements with array}§7930 T * alloc_align_set( T ptr[], size_t align, size_t dim, char fill ); §\C{// realloc new aligned array[dim], fill new bytes with value}§7535 T * alloc( size_t dim ); $\C{// array[dim], T size elements}$ 7536 T * alloc( T ptr[], size_t dim ); $\C{// realloc array[dim], T size elements}$ 7537 7538 T * alloc_set( char fill );$\indexc{alloc_set}$ $\C{// variable, T size, fill bytes with value}$ 7539 T * alloc_set( T fill ); $\C{// variable, T size, fill with value}$ 7540 T * alloc_set( size_t dim, char fill ); $\C{// array[dim], T size elements, fill bytes with value}$ 7541 T * alloc_set( size_t dim, T fill ); $\C{// array[dim], T size elements, fill elements with value}$ 7542 T * alloc_set( size_t dim, const T fill[] ); $\C{// array[dim], T size elements, fill elements with array}$ 7543 T * alloc_set( T ptr[], size_t dim, char fill ); $\C{// realloc array[dim], T size elements, fill bytes with value}$ 7544 7545 T * alloc_align( size_t align ); $\C{// aligned variable, T size}$ 7546 T * alloc_align( size_t align, size_t dim ); $\C{// aligned array[dim], T size elements}$ 7547 T * alloc_align( T ptr[], size_t align ); $\C{// realloc new aligned array}$ 7548 T * alloc_align( T ptr[], size_t align, size_t dim ); $\C{// realloc new aligned array[dim]}$ 7549 7550 T * alloc_align_set( size_t align, char fill ); $\C{// aligned variable, T size, fill bytes with value}$ 7551 T * alloc_align_set( size_t align, T fill ); $\C{// aligned variable, T size, fill with value}$ 7552 T * alloc_align_set( size_t align, size_t dim, char fill ); $\C{// aligned array[dim], T size elements, fill bytes with value}$ 7553 T * alloc_align_set( size_t align, size_t dim, T fill ); $\C{// aligned array[dim], T size elements, fill elements with value}$ 7554 T * alloc_align_set( size_t align, size_t dim, const T fill[] ); $\C{// aligned array[dim], T size elements, fill elements with array}$ 7555 T * alloc_align_set( T ptr[], size_t align, size_t dim, char fill ); $\C{// realloc new aligned array[dim], fill new bytes with value}$ 7931 7556 7932 7557 // $\CFA$ safe initialization/copy, i.e., implicit size specification … … 7989 7614 \leavevmode 7990 7615 \begin{cfa}[aboveskip=0pt,belowskip=0pt] 7991 forall( T | { int ?<?( T, T ); } ) §\C{// location}§7616 forall( T | { int ?<?( T, T ); } ) $\C{// location}$ 7992 7617 T * bsearch( T key, const T * arr, size_t dim );$\indexc{bsearch}$ 7993 7618 7994 forall( T | { int ?<?( T, T ); } ) §\C{// position}§7619 forall( T | { int ?<?( T, T ); } ) $\C{// position}$ 7995 7620 unsigned int bsearch( T key, const T * arr, size_t dim ); 7996 7621 … … 7999 7624 8000 7625 forall( E | { int ?<?( E, E ); } ) { 8001 E * bsearch( E key, const E * vals, size_t dim );$\indexc{bsearch}$ §\C{// location}§8002 size_t bsearch( E key, const E * vals, size_t dim ); §\C{// position}§7626 E * bsearch( E key, const E * vals, size_t dim );$\indexc{bsearch}$ $\C{// location}$ 7627 size_t bsearch( E key, const E * vals, size_t dim );$\C{// position}$ 8003 7628 E * bsearchl( E key, const E * vals, size_t dim );$\indexc{bsearchl}$ 8004 7629 size_t bsearchl( E key, const E * vals, size_t dim ); … … 8047 7672 void srandom( unsigned int seed );$\indexc{srandom}$ 8048 7673 char random( void );$\indexc{random}$ 8049 char random( char u ); §\C{// [0,u)}§8050 char random( char l, char u ); §\C{// [l,u]}§7674 char random( char u ); $\C{// [0,u)}$ 7675 char random( char l, char u ); $\C{// [l,u]}$ 8051 7676 int random( void ); 8052 int random( int u ); §\C{// [0,u)}§8053 int random( int l, int u ); §\C{// [l,u]}§7677 int random( int u ); $\C{// [0,u)}$ 7678 int random( int l, int u ); $\C{// [l,u]}$ 8054 7679 unsigned int random( void ); 8055 unsigned int random( unsigned int u ); §\C{// [0,u)}§8056 unsigned int random( unsigned int l, unsigned int u ); §\C{// [l,u]}§7680 unsigned int random( unsigned int u ); $\C{// [0,u)}$ 7681 unsigned int random( unsigned int l, unsigned int u ); $\C{// [l,u]}$ 8057 7682 long int random( void ); 8058 long int random( long int u ); §\C{// [0,u)}§8059 long int random( long int l, long int u ); §\C{// [l,u]}§7683 long int random( long int u ); $\C{// [0,u)}$ 7684 long int random( long int l, long int u ); $\C{// [l,u]}$ 8060 7685 unsigned long int random( void ); 8061 unsigned long int random( unsigned long int u ); §\C{// [0,u)}§8062 unsigned long int random( unsigned long int l, unsigned long int u ); §\C{// [l,u]}§8063 float random( void ); §\C{// [0.0, 1.0)}§8064 double random( void ); §\C{// [0.0, 1.0)}§8065 float _Complex random( void ); §\C{// [0.0, 1.0)+[0.0, 1.0)i}§8066 double _Complex random( void ); §\C{// [0.0, 1.0)+[0.0, 1.0)i}§8067 long double _Complex random( void ); §\C{// [0.0, 1.0)+[0.0, 1.0)i}§7686 unsigned long int random( unsigned long int u ); $\C{// [0,u)}$ 7687 unsigned long int random( unsigned long int l, unsigned long int u ); $\C{// [l,u]}$ 7688 float random( void ); $\C{// [0.0, 1.0)}$ 7689 double random( void ); $\C{// [0.0, 1.0)}$ 7690 float _Complex random( void ); $\C{// [0.0, 1.0)+[0.0, 1.0)i}$ 7691 double _Complex random( void ); $\C{// [0.0, 1.0)+[0.0, 1.0)i}$ 7692 long double _Complex random( void ); $\C{// [0.0, 1.0)+[0.0, 1.0)i}$ 8068 7693 \end{cfa} 8069 7694 … … 8264 7889 long double atan2( long double, long double ); 8265 7890 8266 float atan( float, float ); §\C{// alternative name for atan2}§7891 float atan( float, float ); $\C{// alternative name for atan2}$ 8267 7892 double atan( double, double );$\indexc{atan}$ 8268 7893 long double atan( long double, long double ); … … 8491 8116 \begin{cfa}[aboveskip=0pt,belowskip=0pt] 8492 8117 struct Duration { 8493 int64_t tn; §\C{// nanoseconds}§8118 int64_t tn; $\C{// nanoseconds}$ 8494 8119 }; 8495 8120 … … 8636 8261 \begin{cfa}[aboveskip=0pt,belowskip=0pt] 8637 8262 struct Time { 8638 uint64_t tn; §\C{// nanoseconds since UNIX epoch}§8263 uint64_t tn; $\C{// nanoseconds since UNIX epoch}$ 8639 8264 }; 8640 8265 … … 8701 8326 \leavevmode 8702 8327 \begin{cfa}[aboveskip=0pt,belowskip=0pt] 8703 struct Clock { §\C{// virtual clock}§8704 Duration offset; §\C{// offset from computer real-time}§8328 struct Clock { $\C{// virtual clock}$ 8329 Duration offset; $\C{// offset from computer real-time}$ 8705 8330 }; 8706 8331 8707 void ?{}( Clock & clk ); §\C{// create no offset}§8708 void ?{}( Clock & clk, Duration adj ); §\C{// create with offset}§8709 void reset( Clock & clk, Duration adj ); §\C{// change offset}§8710 8711 Duration resolutionHi(); §\C{// clock resolution in nanoseconds (fine)}§8712 Duration resolution(); §\C{// clock resolution without nanoseconds (coarse)}§8713 8714 Time timeHiRes(); §\C{// real time with nanoseconds}§8715 Time time(); §\C{// real time without nanoseconds}§8716 Time time( Clock & clk ); §\C{// real time for given clock}§8717 Time ?()( Clock & clk ); §\C{//\ \ \ \ alternative syntax}§8718 timeval time( Clock & clk ); §\C{// convert to C time format}§8332 void ?{}( Clock & clk ); $\C{// create no offset}$ 8333 void ?{}( Clock & clk, Duration adj ); $\C{// create with offset}$ 8334 void reset( Clock & clk, Duration adj ); $\C{// change offset}$ 8335 8336 Duration resolutionHi(); $\C{// clock resolution in nanoseconds (fine)}$ 8337 Duration resolution(); $\C{// clock resolution without nanoseconds (coarse)}$ 8338 8339 Time timeHiRes(); $\C{// real time with nanoseconds}$ 8340 Time time(); $\C{// real time without nanoseconds}$ 8341 Time time( Clock & clk ); $\C{// real time for given clock}$ 8342 Time ?()( Clock & clk ); $\C{//\ \ \ \ alternative syntax}$ 8343 timeval time( Clock & clk ); $\C{// convert to C time format}$ 8719 8344 tm time( Clock & clk ); 8720 Duration processor(); §\C{// non-monotonic duration of kernel thread}§8721 Duration program(); §\C{// non-monotonic duration of program CPU}§8722 Duration boot(); §\C{// monotonic duration since computer boot}§8345 Duration processor(); $\C{// non-monotonic duration of kernel thread}$ 8346 Duration program(); $\C{// non-monotonic duration of program CPU}$ 8347 Duration boot(); $\C{// monotonic duration since computer boot}$ 8723 8348 \end{cfa} 8724 8349 … … 8761 8386 \begin{cfa} 8762 8387 struct PRNG { ... }; $\C[3.75in]{// opaque type}$ 8763 void ?{}( PRNG & prng ); §\C{// random seed}§8764 void ?{}( PRNG & prng, uint32_t seed ); §\C{// fixed seed}§8765 void set_seed( PRNG & prng, uint32_t seed ); §\C{// set seed}§8766 uint32_t get_seed( PRNG & prng ); §\C{// get seed}§8767 uint32_t prng( PRNG & prng ); §\C{// [0,UINT\_MAX]}§8768 uint32_t prng( PRNG & prng, uint32_t u ); §\C{// [0,u)}§8769 uint32_t prng( PRNG & prng, uint32_t l, uint32_t u ); §\C{// [l,u]}§8770 uint32_t calls( PRNG & prng ); §\C{// number of calls}\CRT§8388 void ?{}( PRNG & prng ); $\C{// random seed}$ 8389 void ?{}( PRNG & prng, uint32_t seed ); $\C{// fixed seed}$ 8390 void set_seed( PRNG & prng, uint32_t seed ); $\C{// set seed}$ 8391 uint32_t get_seed( PRNG & prng ); $\C{// get seed}$ 8392 uint32_t prng( PRNG & prng ); $\C{// [0,UINT\_MAX]}$ 8393 uint32_t prng( PRNG & prng, uint32_t u ); $\C{// [0,u)}$ 8394 uint32_t prng( PRNG & prng, uint32_t l, uint32_t u ); $\C{// [l,u]}$ 8395 uint32_t calls( PRNG & prng ); $\C{// number of calls}\CRT$ 8771 8396 \end{cfa} 8772 8397 A ©PRNG© object is used to randomize behaviour or values during execution, \eg in games, a character makes a random move or an object takes on a random value. … … 8822 8447 \begin{cfa} 8823 8448 void set_seed( uint32_t seed ); $\C[3.75in]{// set global seed}$ 8824 uint32_t get_seed(); §\C{// get global seed}§8449 uint32_t get_seed(); $\C{// get global seed}$ 8825 8450 // SLOWER 8826 uint32_t prng(); §\C{// [0,UINT\_MAX]}§8827 uint32_t prng( uint32_t u ); §\C{// [0,u)}§8828 uint32_t prng( uint32_t l, uint32_t u ); §\C{// [l,u]}§8451 uint32_t prng(); $\C{// [0,UINT\_MAX]}$ 8452 uint32_t prng( uint32_t u ); $\C{// [0,u)}$ 8453 uint32_t prng( uint32_t l, uint32_t u ); $\C{// [l,u]}$ 8829 8454 // FASTER 8830 uint32_t prng( $thread\LstStringStyle{\textdollar}$ & th ); §\C{// [0,UINT\_MAX]}§8831 uint32_t prng( $thread\LstStringStyle{\textdollar}$ & th, uint32_t u ); §\C{// [0,u)}§8832 uint32_t prng( $thread\LstStringStyle{\textdollar}$ & th, uint32_t l, uint32_t u ); §\C{// [l,u]}\CRT§8455 uint32_t prng( $thread\LstStringStyle{\textdollar}$ & th ); $\C{// [0,UINT\_MAX]}$ 8456 uint32_t prng( $thread\LstStringStyle{\textdollar}$ & th, uint32_t u ); $\C{// [0,u)}$ 8457 uint32_t prng( $thread\LstStringStyle{\textdollar}$ & th, uint32_t l, uint32_t u ); $\C{// [l,u]}\CRT$ 8833 8458 \end{cfa} 8834 8459 The only difference between the two sets of ©prng© routines is performance. … … 8911 8536 8912 8537 \begin{cfa} 8913 void ?{}( Int * this ); §\C{// constructor/destructor}§8538 void ?{}( Int * this ); $\C{// constructor/destructor}$ 8914 8539 void ?{}( Int * this, Int init ); 8915 8540 void ?{}( Int * this, zero_t ); … … 8920 8545 void ^?{}( Int * this ); 8921 8546 8922 Int ?=?( Int * lhs, Int rhs ); §\C{// assignment}§8547 Int ?=?( Int * lhs, Int rhs ); $\C{// assignment}$ 8923 8548 Int ?=?( Int * lhs, long int rhs ); 8924 8549 Int ?=?( Int * lhs, unsigned long int rhs ); … … 8937 8562 unsigned long int narrow( Int val ); 8938 8563 8939 int ?==?( Int oper1, Int oper2 ); §\C{// comparison}§8564 int ?==?( Int oper1, Int oper2 ); $\C{// comparison}$ 8940 8565 int ?==?( Int oper1, long int oper2 ); 8941 8566 int ?==?( long int oper2, Int oper1 ); … … 8973 8598 int ?>=?( unsigned long int oper1, Int oper2 ); 8974 8599 8975 Int +?( Int oper ); §\C{// arithmetic}§8600 Int +?( Int oper ); $\C{// arithmetic}$ 8976 8601 Int -?( Int oper ); 8977 8602 Int ~?( Int oper ); … … 9055 8680 Int ?>>=?( Int * lhs, mp_bitcnt_t shift ); 9056 8681 9057 Int abs( Int oper ); §\C{// number functions}§8682 Int abs( Int oper ); $\C{// number functions}$ 9058 8683 Int fact( unsigned long int N ); 9059 8684 Int gcd( Int oper1, Int oper2 ); … … 9067 8692 Int sqrt( Int oper ); 9068 8693 9069 forall( dtype istype | istream( istype ) ) istype * ?|?( istype * is, Int * mp ); §\C{// I/O}§8694 forall( dtype istype | istream( istype ) ) istype * ?|?( istype * is, Int * mp ); $\C{// I/O}$ 9070 8695 forall( dtype ostype | ostream( ostype ) ) ostype * ?|?( ostype * os, Int mp ); 9071 8696 \end{cfa} … … 9166 8791 // implementation 9167 8792 struct Rational {$\indexc{Rational}$ 9168 long int numerator, denominator; §\C{// invariant: denominator > 0}§8793 long int numerator, denominator; $\C{// invariant: denominator > 0}$ 9169 8794 }; // Rational 9170 8795 9171 Rational rational(); §\C{// constructors}§8796 Rational rational(); $\C{// constructors}$ 9172 8797 Rational rational( long int n ); 9173 8798 Rational rational( long int n, long int d ); … … 9175 8800 void ?{}( Rational * r, one_t ); 9176 8801 9177 long int numerator( Rational r ); §\C{// numerator/denominator getter/setter}§8802 long int numerator( Rational r ); $\C{// numerator/denominator getter/setter}$ 9178 8803 long int numerator( Rational r, long int n ); 9179 8804 long int denominator( Rational r ); 9180 8805 long int denominator( Rational r, long int d ); 9181 8806 9182 int ?==?( Rational l, Rational r ); §\C{// comparison}§8807 int ?==?( Rational l, Rational r ); $\C{// comparison}$ 9183 8808 int ?!=?( Rational l, Rational r ); 9184 8809 int ?<?( Rational l, Rational r ); … … 9187 8812 int ?>=?( Rational l, Rational r ); 9188 8813 9189 Rational -?( Rational r ); §\C{// arithmetic}§8814 Rational -?( Rational r ); $\C{// arithmetic}$ 9190 8815 Rational ?+?( Rational l, Rational r ); 9191 8816 Rational ?-?( Rational l, Rational r ); … … 9193 8818 Rational ?/?( Rational l, Rational r ); 9194 8819 9195 double widen( Rational r ); §\C{// conversion}§8820 double widen( Rational r ); $\C{// conversion}$ 9196 8821 Rational narrow( double f, long int md ); 9197 8822 -
libcfa/src/Makefile.am
rf988834 r59c8dff 48 48 math.trait.hfa \ 49 49 math.hfa \ 50 raii.hfa \51 50 time_t.hfa \ 52 51 virtual_dtor.hfa \ -
libcfa/src/collections/array.hfa
rf988834 r59c8dff 131 131 132 132 static inline void __taglen( tag(arpk(N, S, Timmed, Tbase)), tag(N) ) {} 133 } 134 135 // RAII pattern has workarounds for 136 // - Trac 226: Simplest handling would be, require immediate element to be otype, let autogen 137 // raii happen. Performance on even a couple dimensions is unacceptable because of exponential 138 // thunk creation: ?{}() needs all four otype funcs from next level, so does ^?{}(), so do the 139 // other two. This solution offers ?{}() that needs only ?{}(), and similar for ^?{}. 140 141 forall( [N], S & | sized(S), Timmed &, Tbase & | { void ?{}( Timmed & ); } ) 142 static inline void ?{}( arpk(N, S, Timmed, Tbase) & this ) { 143 void ?{}( S (&)[N] ) {} 144 ?{}(this.strides); 145 146 for (i; N) ?{}( (Timmed &) this.strides[i] ); 147 } 148 149 forall( [N], S & | sized(S), Timmed &, Tbase & | { void ^?{}( Timmed & ); } ) 150 static inline void ^?{}( arpk(N, S, Timmed, Tbase) & this ) { 151 void ^?{}( S (&)[N] ) {} 152 ^?{}(this.strides); 153 154 for (i; N ) { 155 ^?{}( (Timmed &) this.strides[N-i-1] ); 133 134 // workaround #226 (and array relevance thereof demonstrated in mike102/otype-slow-ndims.cfa) 135 static inline void ?{}( arpk(N, S, Timmed, Tbase) & this ) { 136 void ?{}( S (&inner)[N] ) {} 137 ?{}(this.strides); 138 } 139 static inline void ^?{}( arpk(N, S, Timmed, Tbase) & this ) { 140 void ^?{}( S (&inner)[N] ) {} 141 ^?{}(this.strides); 156 142 } 157 143 } … … 161 147 // 162 148 163 forall( Te *)149 forall( Te ) 164 150 static inline Te mkar_( tag(Te) ) {} 165 151 -
libcfa/src/collections/string.cfa
rf988834 r59c8dff 10 10 // Created On : Fri Sep 03 11:00:00 2021 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun Jan 14 12:03:47 202413 // Update Count : 2 4012 // Last Modified On : Wed Oct 18 21:52:09 2023 13 // Update Count : 208 14 14 // 15 15 … … 29 29 // string RAII 30 30 31 32 void ?{}( string & this ) { 33 (this.inner) { malloc() }; 34 ?{}( *this.inner ); 35 } 36 31 37 // private (not in header) 32 static void ?{}( string & s, string_res & src, size_t start, size_t len ) { 33 (s.inner) { malloc() }; 34 ?{}( *s.inner, src, SHARE_EDITS, start, len ); 35 } 36 37 void ?{}( string & s ) { 38 (s.inner) { malloc() }; 39 ?{}( *s.inner ); 40 } 41 42 void ?{}( string & s, const string & c ) { 43 (s.inner) { malloc() }; 44 ?{}( *s.inner, *c.inner, COPY_VALUE ); 45 } 46 47 void ?{}( string & s, const string & s2, size_t maxlen) { 48 (s.inner) { malloc() }; 49 ?{}( *s.inner, *s2.inner, COPY_VALUE, maxlen ); 50 } 51 52 53 void ?{}( string & s, string & c ) { 54 ?{}( s, (const string &) c ); 55 } 56 57 void ?{}( string & s, const char c ) { 58 (s.inner) { malloc() }; 59 ?{}( *s.inner, c ); 60 } 61 62 void ?{}( string & s, const char * c ) { 63 (s.inner) { malloc() }; 64 ?{}( *s.inner, c ); 65 } 66 67 void ?{}( string & s, const char * c, size_t size) { 68 (s.inner) { malloc() }; 69 ?{}( *s.inner, c, size ); 70 } 71 72 void ^?{}( string & s ) { 73 ^(*s.inner){}; 74 free( s.inner ); 75 s.inner = 0p; 38 static void ?{}( string & this, string_res & src, size_t start, size_t end ) { 39 (this.inner) { malloc() }; 40 ?{}( *this.inner, src, SHARE_EDITS, start, end ); 41 } 42 43 void ?{}( string & this, const string & other ) { 44 (this.inner) { malloc() }; 45 ?{}( *this.inner, *other.inner, COPY_VALUE ); 46 } 47 48 void ?{}( string & this, string & other ) { 49 ?{}( this, (const string &) other ); 50 } 51 52 void ?{}( string & this, const char * val ) { 53 (this.inner) { malloc() }; 54 ?{}( *this.inner, val ); 55 } 56 57 void ?{}( string & this, const char * buffer, size_t bsize) { 58 (this.inner) { malloc() }; 59 ?{}( *this.inner, buffer, bsize ); 60 } 61 62 void ^?{}( string & this ) { 63 ^(*this.inner){}; 64 free( this.inner ); 65 this.inner = 0p; 76 66 } 77 67 … … 79 69 // Alternate construction: request shared edits 80 70 81 string_WithSharedEdits ?`shareEdits( string & s ) {82 string_WithSharedEdits ret = { & s };83 return ret; 84 } 85 86 void ?{}( string & s, string_WithSharedEdits src ) {87 ?{}( s, *src.s->inner, 0, src.s->inner->Handle.lnth);71 string_WithSharedEdits ?`shareEdits( string & this ) { 72 string_WithSharedEdits ret = { &this }; 73 return ret; 74 } 75 76 void ?{}( string & this, string_WithSharedEdits src ) { 77 ?{}( this, *src.s->inner, 0, src.s->inner->Handle.lnth); 88 78 } 89 79 … … 91 81 // Assignment 92 82 93 void ?=?( string & s, const char * val ) { 94 (*s.inner) = val; 95 } 96 97 // with and without const on "other" argument helps keep prevent autogen ?=? calls 98 void ?=?(string & s, const string & c) { 99 (*s.inner) = (*c.inner); 100 } 101 string & ?=?(string & s, string & c) { 102 (*s.inner) = (*c.inner); 103 return s; 104 } 105 106 void ?=?( string & s, char val ) { 107 (*s.inner) = val; 108 } 109 110 void assign(string & s, const string & c, size_t n) { 111 assign(*s.inner, *c.inner, n); 112 } 113 void assign(string & s, const char * c, size_t n) { 114 assign(*s.inner, c, n); 83 void ?=?( string & this, const char * val ) { 84 (*this.inner) = val; 85 } 86 87 void ?=?(string & this, const string & other) { 88 (*this.inner) = (*other.inner); 89 } 90 91 void ?=?( string & this, char val ) { 92 (*this.inner) = val; 93 } 94 95 string & ?=?(string & this, string & other) { //// <---- straw man change 96 (*this.inner) = (*other.inner); 97 return this; 115 98 } 116 99 … … 119 102 // Input-Output 120 103 121 ofstream & ?|?( ofstream & out, const string & s ) {122 return out | (* s.inner); // print internal string_res123 } 124 125 void ?|?( ofstream & out, const string & s ) {126 (ofstream &)(out | (* s.inner)); ends( out );104 ofstream & ?|?( ofstream & out, const string & this ) { 105 return out | (*this.inner); // print internal string_res 106 } 107 108 void ?|?( ofstream & out, const string & this ) { 109 (ofstream &)(out | (*this.inner)); ends( out ); 127 110 } 128 111 … … 141 124 } 142 125 143 ifstream & ?|?(ifstream & in, string & s) {144 return in | (* s.inner); // read to internal string_res145 } 146 147 void ?|?( ifstream & in, string & s ) {148 in | (* s.inner);126 ifstream & ?|?(ifstream & in, string & this) { 127 return in | (*this.inner); // read to internal string_res 128 } 129 130 void ?|?( ifstream & in, string & this ) { 131 in | (*this.inner); 149 132 } 150 133 … … 161 144 // Slicing 162 145 163 string ?()( string & s, size_t start, size_t len) {164 string ret = { * s.inner, start, len};146 string ?()( string & this, size_t start, size_t end ) { 147 string ret = { *this.inner, start, end }; 165 148 return ret`shareEdits; 166 149 } 167 150 168 string ?()( string & s, size_t start ) {169 string ret = { * s.inner, start, size( s ) - start};151 string ?()( string & this, size_t start ) { 152 string ret = { *this.inner, start, size( this ) }; 170 153 return ret`shareEdits; 171 154 } … … 174 157 // Comparison 175 158 176 int strcmp(const string & s1, const string & s2) { return strcmp(*s1.inner,*s2.inner); }177 bool ?==?(const string & s1, const string & s2) { return *s1.inner == *s2.inner; }178 bool ?!=?(const string & s1, const string & s2) { return *s1.inner != *s2.inner; }179 bool ?>? (const string & s1, const string & s2) { return *s1.inner > *s2.inner; }180 bool ?>=?(const string & s1, const string & s2) { return *s1.inner >= *s2.inner; }181 bool ?<=?(const string & s1, const string & s2) { return *s1.inner <= *s2.inner; }182 bool ?<? (const string & s1, const string & s2) { return *s1.inner < *s2.inner; }183 184 int strcmp(const string & s1, const char * s2) { return strcmp(*s1.inner, s2); }185 bool ?==?(const string & s1, const char * s2) { return *s1.inner == s2; }186 bool ?!=?(const string & s1, const char * s2) { return *s1.inner != s2; }187 bool ?>? (const string & s1, const char * s2) { return *s1.inner > s2; }188 bool ?>=?(const string & s1, const char * s2) { return *s1.inner >= s2; }189 bool ?<=?(const string & s1, const char * s2) { return *s1.inner <= s2; }190 bool ?<? (const string & s1, const char * s2) { return *s1.inner < s2; }191 192 int strcmp(const char * s1, const string & s2) { return strcmp( s1,*s2.inner); }193 bool ?==?(const char * s1, const string & s2) { return s1 == *s2.inner; }194 bool ?!=?(const char * s1, const string & s2) { return s1 != *s2.inner; }195 bool ?>? (const char * s1, const string & s2) { return s1 > *s2.inner; }196 bool ?>=?(const char * s1, const string & s2) { return s1 >= *s2.inner; }197 bool ?<=?(const char * s1, const string & s2) { return s1 <= *s2.inner; }198 bool ?<? (const char * s1, const string & s2) { return s1 < *s2.inner; }159 int cmp (const string &s1, const string &s2) { return cmp(*s1.inner , *s2.inner); } 160 bool ?==?(const string &s1, const string &s2) { return *s1.inner == *s2.inner ; } 161 bool ?!=?(const string &s1, const string &s2) { return *s1.inner != *s2.inner ; } 162 bool ?>? (const string &s1, const string &s2) { return *s1.inner > *s2.inner ; } 163 bool ?>=?(const string &s1, const string &s2) { return *s1.inner >= *s2.inner ; } 164 bool ?<=?(const string &s1, const string &s2) { return *s1.inner <= *s2.inner ; } 165 bool ?<? (const string &s1, const string &s2) { return *s1.inner < *s2.inner ; } 166 167 int cmp (const string &s1, const char* s2) { return cmp(*s1.inner , s2 ); } 168 bool ?==?(const string &s1, const char* s2) { return *s1.inner == s2 ; } 169 bool ?!=?(const string &s1, const char* s2) { return *s1.inner != s2 ; } 170 bool ?>? (const string &s1, const char* s2) { return *s1.inner > s2 ; } 171 bool ?>=?(const string &s1, const char* s2) { return *s1.inner >= s2 ; } 172 bool ?<=?(const string &s1, const char* s2) { return *s1.inner <= s2 ; } 173 bool ?<? (const string &s1, const char* s2) { return *s1.inner < s2 ; } 174 175 int cmp (const char* s1, const string &s2) { return cmp( s1 , *s2.inner); } 176 bool ?==?(const char* s1, const string &s2) { return s1 == *s2.inner ; } 177 bool ?!=?(const char* s1, const string &s2) { return s1 != *s2.inner ; } 178 bool ?>? (const char* s1, const string &s2) { return s1 > *s2.inner ; } 179 bool ?>=?(const char* s1, const string &s2) { return s1 >= *s2.inner ; } 180 bool ?<=?(const char* s1, const string &s2) { return s1 <= *s2.inner ; } 181 bool ?<? (const char* s1, const string &s2) { return s1 < *s2.inner ; } 199 182 200 183 … … 203 186 204 187 size_t size(const string & s) { 205 return size( * s.inner );188 return size( * s.inner ); 206 189 } 207 190 … … 209 192 // Concatenation 210 193 211 void ?+=?(string & s, char c) {212 (*s.inner) += c;194 void ?+=?(string & s, char other) { 195 (*s.inner) += other; 213 196 } 214 197 … … 217 200 } 218 201 219 void append(string & s, const string & s2, size_t maxlen) { 220 append( (*s.inner), (*s2.inner), maxlen ); 221 } 222 223 void ?+=?(string & s, const char * c) { 224 (*s.inner) += c; 225 } 226 227 void append(string & s, const char * buffer, size_t bsize) { 228 append( (*s.inner), buffer, bsize ); 229 } 230 231 string ?+?(const string & s, char c) { 202 void ?+=?(string & s, const char * other) { 203 (*s.inner) += other; 204 } 205 206 string ?+?(const string & s, char other) { 232 207 string ret = s; 233 ret += c;208 ret += other; 234 209 return ret; 235 210 } … … 247 222 } 248 223 249 string ?+?(const string & s, const char * c) {224 string ?+?(const string & s, const char * other) { 250 225 string ret = s; 251 ret += c;226 ret += other; 252 227 return ret; 253 228 } … … 256 231 // Repetition 257 232 258 void ?*=?(string & s, size_t factor) {259 (*s.inner) *= factor;260 }261 262 233 string ?*?(const string & s, size_t factor) { 263 string ret = s; 264 ret *= factor; 265 return ret; 266 } 267 268 string ?*?(char c, size_t factor) { 269 string ret = c; 270 ret *= factor; 271 return ret; 272 } 273 274 string ?*?(const char * s, size_t factor) { 275 string ret = s; 276 ret *= factor; 277 return ret; 234 string ret = ""; 235 for (factor) ret += s; 236 return ret; 237 } 238 239 string ?*?(char c, size_t size) { 240 string ret = ""; 241 for ((size_t)size) ret += c; 242 return ret; 243 } 244 245 string ?*?(const char *s, size_t factor) { 246 string ss = s; 247 return ss * factor; 278 248 } 279 249 … … 286 256 287 257 string ?[?](string & s, size_t index) { 288 string ret = { *s.inner, index, 1 };258 string ret = { *s.inner, index, index + 1 }; 289 259 return ret`shareEdits; 290 260 } … … 369 339 // charclass, include, exclude 370 340 371 void ?{}( charclass & s, const string & chars) {372 ( s.inner) { malloc() };373 ?{}( * s.inner, *(const string_res *)chars.inner );374 } 375 376 void ?{}( charclass & s, const char * chars ) {377 ( s.inner) { malloc() };378 ?{}( * s.inner, chars );379 } 380 381 void ?{}( charclass & s, const char * chars, size_t charssize ) {382 ( s.inner) { malloc() };383 ?{}( * s.inner, chars, charssize );384 } 385 386 void ^?{}( charclass & s ) {387 ^(* s.inner){};388 free( s.inner );389 s.inner = 0p;341 void ?{}( charclass & this, const string & chars) { 342 (this.inner) { malloc() }; 343 ?{}( *this.inner, *(const string_res *)chars.inner ); 344 } 345 346 void ?{}( charclass & this, const char * chars ) { 347 (this.inner) { malloc() }; 348 ?{}( *this.inner, chars ); 349 } 350 351 void ?{}( charclass & this, const char * chars, size_t charssize ) { 352 (this.inner) { malloc() }; 353 ?{}( *this.inner, chars, charssize ); 354 } 355 356 void ^?{}( charclass & this ) { 357 ^(*this.inner){}; 358 free( this.inner ); 359 this.inner = 0p; 390 360 } 391 361 -
libcfa/src/collections/string.hfa
rf988834 r59c8dff 10 10 // Created On : Fri Sep 03 11:00:00 2021 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : S un Jan 14 12:03:46 202413 // Update Count : 8112 // Last Modified On : Sat Sep 2 11:26:28 2023 13 // Update Count : 55 14 14 // 15 15 … … 29 29 // Getters 30 30 size_t size(const string & s); 31 static inline size_t strlen(const string & s) { return size( s ); }32 31 33 32 // RAII, assignment 34 void ?{}(string & s); // empty string 33 void ?{}(string & this); // empty string 34 void ?{}(string & s, const char * initial); // copy from string literal (NULL-terminated) 35 void ?{}(string & s, const char * buffer, size_t bsize); // copy specific length from buffer 36 35 37 void ?{}(string & s, const string & s2); 36 void ?{}(string & s, const string & s2, size_t maxlen);37 38 void ?{}(string & s, string & s2); 38 39 39 void ?{}(string & s, char); 40 void ?{}(string & s, const char * c); // copy from string literal (NULL-terminated) 41 void ?{}(string & s, const char * c, size_t size); // copy specific length from buffer 42 43 void ?=?(string & s, const char * c); // copy assignment from literal 44 void ?=?(string & s, const string & c); 45 void ?=?(string & s, char c); 46 string & ?=?(string & s, string & c); // surprising ret seems to help avoid calls to autogen 47 void assign(string & s, const string & c, size_t n); 48 void assign(string & s, const char * c, size_t n); 40 void ?=?(string & s, const char * other); // copy assignment from literal 41 void ?=?(string & s, const string & other); 42 void ?=?(string & s, char other); 43 string & ?=?(string & s, string & other); // surprising ret seems to help avoid calls to autogen 49 44 //string ?=?( string &, string ) = void; 50 51 static inline string & strcpy(string & s, const char * c) { s = c; return s; }52 static inline string & strncpy(string & s, const char * c, size_t n) { assign( s, c, n); return s; }53 static inline string & strcpy(string & s, const string & c) { s = c; return s; }54 static inline string & strncpy(string & s, const string & c, size_t n) { assign(s, c, n); return s; }55 56 45 void ^?{}(string & s); 57 46 … … 60 49 string * s; 61 50 }; 62 string_WithSharedEdits ?`shareEdits( string & s );63 void ?{}( string & s, string_WithSharedEdits src );51 string_WithSharedEdits ?`shareEdits( string & this ); 52 void ?{}( string & this, string_WithSharedEdits src ); 64 53 65 54 // IO Operator … … 67 56 void ?|?(ofstream & out, const string & s); 68 57 ifstream & ?|?(ifstream & in, string & s); 69 void ?|?( ifstream & in, string & s );58 void ?|?( ifstream & in, string & this ); 70 59 71 60 static inline { … … 92 81 _Istream_Sstr wdi( unsigned int rwd, string & s ) { return (_Istream_Sstr)@{ s, {{0p}, rwd, {.flags.rwd : true}} }; } 93 82 _Istream_Sstr getline( string & s, const char delimiter = '\n' ) { 94 return (_Istream_Sstr)@{ s, {{.delimiter s: { delimiter, '\0' } }, -1, {.flags.delimiter : true, .flags.inex : true}} };83 return (_Istream_Sstr)@{ s, {{.delimiter : { delimiter, '\0' } }, -1, {.flags.delimiter : true, .flags.inex : true}} }; 95 84 } 96 85 _Istream_Sstr & getline( _Istream_Sstr & fmt, const char delimiter = '\n' ) { 97 fmt.delimiter s[0] = delimiter; fmt.delimiters[1] = '\0'; fmt.flags.delimiter = true; fmt.flags.inex = true; return fmt;86 fmt.delimiter[0] = delimiter; fmt.delimiter[1] = '\0'; fmt.flags.delimiter = true; fmt.flags.inex = true; return fmt; 98 87 } 99 88 _Istream_Sstr incl( const char scanset[], string & s ) { return (_Istream_Sstr)@{ s, {{scanset}, -1, {.flags.inex : false}} }; } … … 108 97 109 98 // Concatenation 110 void ?+=?(string & s, char c); // append a character99 void ?+=?(string & s, char other); // append a character 111 100 void ?+=?(string & s, const string & s2); // append-concatenate to first string 112 void append(string & s, const string & s2, size_t maxlen); // append-concatenate to first string, up to maxlen 113 void ?+=?(string & s, const char * s2); // append-concatenate NULL-terminated string to first string 114 void append(string & s, const char * buffer, size_t bsize); // append-concatenate given range to first string 115 116 string ?+?(const string & s, char c); // add a character to a copy of the string 101 void ?+=?(string & s, const char * other); // append-concatenate to first string 102 string ?+?(const string & s, char other); // add a character to a copy of the string 117 103 string ?+?(const string & s, const string & s2); // copy and concatenate both strings 118 string ?+?(const char * s1, const char * s2); // copy and concatenate both strings 119 string ?+?(const string & s, const char * c); // copy and concatenate with NULL-terminated string 120 121 static inline string & strcat(string & s, const string & s2) { s += s2; return s; } 122 static inline string & strcat(string & s, const char * c) { s += c; return s; } 123 static inline string & strncat(string & s, const string & s2, size_t maxlen) { append(s, s2, maxlen); return s; } 124 static inline string & strncat(string & s, const char * buffer, size_t bsize) { append(s, buffer, bsize); return s; } 104 string ?+?(const char * s1, const char * s2); // concatenate both strings 105 string ?+?(const string & s, const char * other); // copy and concatenate with NULL-terminated string 125 106 126 107 // Repetition 127 108 string ?*?(const string & s, size_t factor); 128 void ?*=?(string & s, size_t factor); 129 string ?*?(char c, size_t factor); 130 string ?*?(const char *s, size_t factor); 109 string ?*?(char c, size_t size); 110 string ?*?(const char *s, size_t size); 131 111 132 112 // Character access … … 136 116 137 117 // Comparisons 138 int strcmp (const string &, const string &);118 int cmp (const string &, const string &); 139 119 bool ?==?(const string &, const string &); 140 120 bool ?!=?(const string &, const string &); … … 144 124 bool ?<? (const string &, const string &); 145 125 146 int strcmp (const string &, const char*);147 bool ?==?(const string &, const char 148 bool ?!=?(const string &, const char 149 bool ?>? (const string &, const char 150 bool ?>=?(const string &, const char 151 bool ?<=?(const string &, const char 152 bool ?<? (const string &, const char 153 154 int strcmp (const char*, const string &);155 bool ?==?(const char 156 bool ?!=?(const char 157 bool ?>? (const char 158 bool ?>=?(const char 159 bool ?<=?(const char 160 bool ?<? (const char 126 int cmp (const string &, const char*); 127 bool ?==?(const string &, const char*); 128 bool ?!=?(const string &, const char*); 129 bool ?>? (const string &, const char*); 130 bool ?>=?(const string &, const char*); 131 bool ?<=?(const string &, const char*); 132 bool ?<? (const string &, const char*); 133 134 int cmp (const char*, const string &); 135 bool ?==?(const char*, const string &); 136 bool ?!=?(const char*, const string &); 137 bool ?>? (const char*, const string &); 138 bool ?>=?(const char*, const string &); 139 bool ?<=?(const char*, const string &); 140 bool ?<? (const char*, const string &); 161 141 162 142 163 143 // Slicing 164 string ?()( string & s, size_t start, size_t len); // TODO const?165 string ?()( string & s, size_t start);144 string ?()( string & this, size_t start, size_t end ); // TODO const? 145 string ?()( string & this, size_t start); 166 146 167 147 // String search … … 197 177 198 178 179 199 180 struct charclass { 200 181 charclass_res * inner; -
libcfa/src/collections/string_res.cfa
rf988834 r59c8dff 10 10 // Created On : Fri Sep 03 11:00:00 2021 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Jan 16 22:19:27 202413 // Update Count : 3512 // Last Modified On : Wed Oct 18 21:54:54 2023 13 // Update Count : 15 14 14 // 15 15 … … 22 22 // Workaround is: EndVbyte = TEMP_ALLOC(char, CurrSize) 23 23 // Should be: EndVbyte = alloc(CurrSize) 24 #define TEMP_ALLOC(T, n) (( T 24 #define TEMP_ALLOC(T, n) (( T* ) malloc( n * sizeof( T ) )) 25 25 26 26 #include <assert.h> … … 33 33 34 34 struct VbyteHeap { 35 int NoOfCompactions; // number of compactions of the byte area 36 int NoOfExtensions; // number of extensions in the size of the byte area 37 int NoOfReductions; // number of reductions in the size of the byte area 35 36 int NoOfCompactions; // number of compactions of the byte area 37 int NoOfExtensions; // number of extensions in the size of the byte area 38 int NoOfReductions; // number of reductions in the size of the byte area 38 39 39 int InitSize; 40 int CurrSize; 41 char *StartVbyte; 42 char *EndVbyte; 43 void *ExtVbyte; 44 45 HandleNode Header; 40 int InitSize; // initial number of bytes in the byte-string area 41 int CurrSize; // current number of bytes in the byte-string area 42 char *StartVbyte; // pointer to the `st byte of the start of the byte-string area 43 char *EndVbyte; // pointer to the next byte after the end of the currently used portion of byte-string area 44 void *ExtVbyte; // pointer to the next byte after the end of the byte-string area 45 46 HandleNode Header; // header node for handle list 46 47 }; // VbyteHeap 47 48 48 49 49 static void compaction( VbyteHeap & ); // compaction of the byte area50 static void garbage( VbyteHeap &, int ); // garbage collect the byte area50 static void compaction( VbyteHeap & ); // compaction of the byte area 51 static void garbage( VbyteHeap &, int ); // garbage collect the byte area 51 52 static void extend( VbyteHeap &, int ); // extend the size of the byte area 52 53 static void reduce( VbyteHeap &, int ); // reduce the size of the byte area … … 66 67 // Allocate the storage for the variable sized area and intialize the heap variables. 67 68 68 static void ?{}( VbyteHeap & s, size_t Size ) with(s) {69 #ifdef VbyteDebug 70 serr | "enter:VbyteHeap::VbyteHeap, s:" | &s | " Size:" | Size;69 static void ?{}( VbyteHeap & this, size_t Size ) with(this) { 70 #ifdef VbyteDebug 71 serr | "enter:VbyteHeap::VbyteHeap, this:" | &this | " Size:" | Size; 71 72 #endif // VbyteDebug 72 73 NoOfCompactions = NoOfExtensions = NoOfReductions = 0; … … 75 76 ExtVbyte = (void *)( StartVbyte + CurrSize ); 76 77 Header.flink = Header.blink = &Header; 77 Header.ulink = & s;78 Header.ulink = & this; 78 79 #ifdef VbyteDebug 79 80 HeaderPtr = &Header; 80 serr | "exit:VbyteHeap::VbyteHeap, s:" | &s;81 serr | "exit:VbyteHeap::VbyteHeap, this:" | &this; 81 82 #endif // VbyteDebug 82 83 } // VbyteHeap … … 85 86 // Release the dynamically allocated storage for the byte area. 86 87 87 static void ^?{}( VbyteHeap & s ) with(s) {88 static void ^?{}( VbyteHeap & this ) with(this) { 88 89 free( StartVbyte ); 89 90 } // ~VbyteHeap … … 96 97 // creator. 97 98 98 static void ?{}( HandleNode & s ) with(s) {99 #ifdef VbyteDebug 100 serr | "enter:HandleNode::HandleNode, s:" | &s;99 static void ?{}( HandleNode & this ) with(this) { 100 #ifdef VbyteDebug 101 serr | "enter:HandleNode::HandleNode, this:" | &this; 101 102 #endif // VbyteDebug 102 103 s = 0; 103 104 lnth = 0; 104 105 #ifdef VbyteDebug 105 serr | "exit:HandleNode::HandleNode, s:" | &s;106 serr | "exit:HandleNode::HandleNode, this:" | &this; 106 107 #endif // VbyteDebug 107 108 } // HandleNode … … 111 112 // collection. 112 113 113 static void ?{}( HandleNode & s, VbyteHeap & vh ) with(s) {114 #ifdef VbyteDebug 115 serr | "enter:HandleNode::HandleNode, s:" | &s;114 static void ?{}( HandleNode & this, VbyteHeap & vh ) with(this) { 115 #ifdef VbyteDebug 116 serr | "enter:HandleNode::HandleNode, this:" | &this; 116 117 #endif // VbyteDebug 117 118 s = 0; 118 119 lnth = 0; 119 120 ulink = &vh; 120 AddThisAfter( s, *vh.Header.blink );121 #ifdef VbyteDebug 122 serr | "exit:HandleNode::HandleNode, s:" | &s;121 AddThisAfter( this, *vh.Header.blink ); 122 #ifdef VbyteDebug 123 serr | "exit:HandleNode::HandleNode, this:" | &this; 123 124 #endif // VbyteDebug 124 125 } // HandleNode … … 128 129 // is the responsibility of the creator to destroy it. 129 130 130 static void ^?{}( HandleNode & s ) with(s) {131 #ifdef VbyteDebug 132 serr | "enter:HandleNode::~HandleNode, s:" | &s;131 static void ^?{}( HandleNode & this ) with(this) { 132 #ifdef VbyteDebug 133 serr | "enter:HandleNode::~HandleNode, this:" | & this; 133 134 { 134 135 serr | nlOff; … … 141 142 } 142 143 #endif // VbyteDebug 143 DeleteNode( s );144 DeleteNode( this ); 144 145 } // ~HandleNode 145 146 … … 150 151 static string_sharectx default_string_sharectx = {NEW_SHARING}; // stable bottom of stack 151 152 152 void ?{}( string_sharectx & s, StringSharectx_Mode mode ) with(s ) {153 void ?{}( string_sharectx & this, StringSharectx_Mode mode ) with( this ) { 153 154 (older){ ambient_string_sharectx }; 154 155 if ( mode == NEW_SHARING ) { … … 158 159 (activeHeap){ 0p }; 159 160 } 160 ambient_string_sharectx = & s;161 } 162 163 void ^?{}( string_sharectx & s ) with(s ) {161 ambient_string_sharectx = & this; 162 } 163 164 void ^?{}( string_sharectx & this ) with( this ) { 164 165 if ( activeHeap ) delete( activeHeap ); 165 166 166 // unlink s from older-list starting from ambient_string_sharectx167 // usually, s==ambient_string_sharectx and the loop runs zero times167 // unlink this from older-list starting from ambient_string_sharectx 168 // usually, this==ambient_string_sharectx and the loop runs zero times 168 169 string_sharectx *& c = ambient_string_sharectx; 169 while ( c != & s ) &c = &c->older; // finds170 c = s.older; // unlink170 while ( c != &this ) &c = &c->older; // find this 171 c = this.older; // unlink 171 172 } 172 173 … … 180 181 181 182 size_t DEBUG_string_bytes_avail_until_gc( VbyteHeap * heap ) { 182 return ((char 183 return ((char*)heap->ExtVbyte) - heap->EndVbyte; 183 184 } 184 185 … … 192 193 193 194 // Returns the size of the string in bytes 194 size_t size(const string_res & 195 size_t size(const string_res &s) with(s) { 195 196 return Handle.lnth; 196 197 } 197 198 198 199 // Output operator 199 ofstream & ?|?(ofstream & out, const string_res &s) {200 ofstream & ?|?(ofstream &out, const string_res &s) { 200 201 // CFA string is NOT null terminated, so print exactly lnth characters in a minimum width of 0. 201 202 out | wd( 0, s.Handle.lnth, s.Handle.s ) | nonl; … … 203 204 } 204 205 205 void ?|?(ofstream & out, const string_res &s) {206 void ?|?(ofstream &out, const string_res &s) { 206 207 (ofstream &)(out | s); ends( out ); 207 208 } 208 209 209 210 // Input operator 210 ifstream & ?|?(ifstream & in, string_res & s) { 211 ifstream & ?|?(ifstream &in, string_res &s) { 212 211 213 // Reading into a temp before assigning to s is near zero overhead in typical cases because of sharing. 212 214 // If s is a substring of something larger, simple assignment takes care of that case correctly. … … 229 231 230 232 // rest of heap is available to read into 231 int lenReadable = (char 233 int lenReadable = (char*)temp.Handle.ulink->ExtVbyte - temp.Handle.ulink->EndVbyte; 232 234 assert (lenReadable >= 2); 233 235 … … 236 238 *(temp.Handle.ulink->EndVbyte) = '\0'; // pre-assign empty cstring 237 239 in | wdi( lenReadable, temp.Handle.ulink->EndVbyte ); 238 } catch (cstring_length 240 } catch (cstring_length*) { 239 241 cont = true; 240 242 } … … 250 252 } 251 253 252 void ?|?( ifstream & in, string_res & s ) {253 (ifstream &)(in | s);254 void ?|?( ifstream & in, string_res & this ) { 255 (ifstream &)(in | this); 254 256 } 255 257 … … 272 274 cont = true; 273 275 } finally { 274 if ( ! cf.flags.ignore // ok to initialize string 275 // && cstr[0] != '\0' // something was read 276 ) { 276 if ( ! cf.flags.ignore && // ok to initialize string 277 cstr[0] != '\0' ) { // something was read 277 278 *(f.s) = cstr; 278 279 } … … 286 287 cont = true; // continue not allowed 287 288 } finally { 288 if ( ! cf.flags.ignore && cstr[0] != '\0' ) { // something was read 289 if ( ! cf.flags.ignore && 290 cstr[0] != '\0' ) { // something was read 289 291 *(f.s) += cstr; // build string chunk at a time 290 292 } … … 300 302 301 303 // Empty constructor 302 void ?{}(string_res & 304 void ?{}(string_res &s) with(s) { 303 305 if( ambient_string_sharectx->activeHeap ) { 304 306 (Handle){ * ambient_string_sharectx->activeHeap }; … … 315 317 } 316 318 317 static void eagerCopyCtorHelper(string_res & s, const char* rhs, size_t rhslnth) with(s) {319 static void eagerCopyCtorHelper(string_res &s, const char* rhs, size_t rhslnth) with(s) { 318 320 if( ambient_string_sharectx->activeHeap ) { 319 321 (Handle){ * ambient_string_sharectx->activeHeap }; … … 331 333 332 334 // Constructor from a raw buffer and size 333 void ?{}(string_res & s, const char* rhs, size_t rhslnth) with(s) {335 void ?{}(string_res &s, const char* rhs, size_t rhslnth) with(s) { 334 336 eagerCopyCtorHelper(s, rhs, rhslnth); 335 337 } 336 338 337 339 // private ctor (not in header): use specified heap (ignore ambient) and copy chars in 338 void ?{}( string_res & s, VbyteHeap & heap, const char* rhs, size_t rhslnth ) with(s) {340 void ?{}( string_res &s, VbyteHeap & heap, const char* rhs, size_t rhslnth ) with(s) { 339 341 (Handle){ heap }; 340 342 Handle.s = VbyteAlloc(*Handle.ulink, rhslnth); … … 346 348 } 347 349 348 349 350 // General copy constructor 350 void ?{}(string_res & s, const string_res & s2, StrResInitMode mode, size_t start, size_t len ) { 351 352 size_t end = start + len; 351 void ?{}(string_res &s, const string_res & s2, StrResInitMode mode, size_t start, size_t end ) { 352 353 353 verify( start <= end && end <= s2.Handle.lnth ); 354 354 … … 394 394 } 395 395 396 static void assignEditSet(string_res & s, string_res * shareEditSetStartPeer, string_res * shareEditSetEndPeer,396 static void assignEditSet(string_res & this, string_res * shareEditSetStartPeer, string_res * shareEditSetEndPeer, 397 397 char * resultSesStart, 398 398 size_t resultSesLnth, … … 400 400 401 401 char * beforeBegin = shareEditSetStartPeer->Handle.s; 402 size_t beforeLen = s.Handle.s - beforeBegin;403 404 char * afterBegin = s.Handle.s +s.Handle.lnth;402 size_t beforeLen = this.Handle.s - beforeBegin; 403 404 char * afterBegin = this.Handle.s + this.Handle.lnth; 405 405 size_t afterLen = shareEditSetEndPeer->Handle.s + shareEditSetEndPeer->Handle.lnth - afterBegin; 406 406 407 size_t oldLnth = s.Handle.lnth;408 409 s.Handle.s = resultSesStart + beforeLen;410 s.Handle.lnth = bsize;407 size_t oldLnth = this.Handle.lnth; 408 409 this.Handle.s = resultSesStart + beforeLen; 410 this.Handle.lnth = bsize; 411 411 if (resultPadPosition) 412 MoveThisAfter( s.Handle, *resultPadPosition );412 MoveThisAfter( this.Handle, *resultPadPosition ); 413 413 414 414 // adjust all substring string and handle locations, and check if any substring strings are outside the new base string 415 415 char *limit = resultSesStart + resultSesLnth; 416 for ( string_res * p = s.shareEditSet_next; p != &s; p = p->shareEditSet_next ) {416 for ( string_res * p = this.shareEditSet_next; p != &this; p = p->shareEditSet_next ) { 417 417 verify (p->Handle.s >= beforeBegin); 418 418 if ( p->Handle.s >= afterBegin ) { … … 439 439 // take end as end-anchored 440 440 // stretch-shrink p according to the edit 441 p->Handle.lnth += s.Handle.lnth;441 p->Handle.lnth += this.Handle.lnth; 442 442 p->Handle.lnth -= oldLnth; 443 443 } … … 452 452 // p ends during the edit; p does not include the last character replaced 453 453 // set p to empty string at start of edit 454 p->Handle.s = s.Handle.s;454 p->Handle.s = this.Handle.s; 455 455 p->Handle.lnth = 0; 456 456 } else { … … 458 458 // clip start of p to start at end of edit 459 459 int charsToClip = afterBegin - p->Handle.s; 460 p->Handle.s = s.Handle.s +s.Handle.lnth;460 p->Handle.s = this.Handle.s + this.Handle.lnth; 461 461 p->Handle.lnth -= charsToClip; 462 462 } … … 467 467 } 468 468 469 // traverse the share-edit set (SES) to recover the range of a base string to which ` s` belongs470 static void locateInShareEditSet( string_res & s, string_res *& shareEditSetStartPeer, string_res *&shareEditSetEndPeer ) {471 shareEditSetStartPeer = & s;472 shareEditSetEndPeer = & s;473 for (string_res * editPeer = s.shareEditSet_next; editPeer != &s; editPeer = editPeer->shareEditSet_next) {469 // traverse the share-edit set (SES) to recover the range of a base string to which `this` belongs 470 static void locateInShareEditSet( string_res &this, string_res *&shareEditSetStartPeer, string_res *&shareEditSetEndPeer ) { 471 shareEditSetStartPeer = & this; 472 shareEditSetEndPeer = & this; 473 for (string_res * editPeer = this.shareEditSet_next; editPeer != &this; editPeer = editPeer->shareEditSet_next) { 474 474 if ( editPeer->Handle.s < shareEditSetStartPeer->Handle.s ) { 475 475 shareEditSetStartPeer = editPeer; … … 481 481 } 482 482 483 static string_res & assign_(string_res & s, const char* buffer, size_t bsize, const string_res & valSrc) {483 static string_res & assign_(string_res &this, const char* buffer, size_t bsize, const string_res & valSrc) { 484 484 485 485 string_res * shareEditSetStartPeer; 486 486 string_res * shareEditSetEndPeer; 487 locateInShareEditSet( s, shareEditSetStartPeer, shareEditSetEndPeer );487 locateInShareEditSet( this, shareEditSetStartPeer, shareEditSetEndPeer ); 488 488 489 489 verify( shareEditSetEndPeer->Handle.s >= shareEditSetStartPeer->Handle.s ); 490 490 size_t origEditSetLength = shareEditSetEndPeer->Handle.s + shareEditSetEndPeer->Handle.lnth - shareEditSetStartPeer->Handle.s; 491 verify( origEditSetLength >= s.Handle.lnth );492 493 if ( s.shareEditSet_owns_ulink ) { // assigning to private context491 verify( origEditSetLength >= this.Handle.lnth ); 492 493 if ( this.shareEditSet_owns_ulink ) { // assigning to private context 494 494 // ok to overwrite old value within LHS 495 495 char * prefixStartOrig = shareEditSetStartPeer->Handle.s; 496 int prefixLen = s.Handle.s - prefixStartOrig;497 char * suffixStartOrig = s.Handle.s +s.Handle.lnth;496 int prefixLen = this.Handle.s - prefixStartOrig; 497 char * suffixStartOrig = this.Handle.s + this.Handle.lnth; 498 498 int suffixLen = shareEditSetEndPeer->Handle.s + shareEditSetEndPeer->Handle.lnth - suffixStartOrig; 499 499 500 int delta = bsize - s.Handle.lnth;501 if ( char * oldBytes = VbyteTryAdjustLast( * s.Handle.ulink, delta ) ) {500 int delta = bsize - this.Handle.lnth; 501 if ( char * oldBytes = VbyteTryAdjustLast( *this.Handle.ulink, delta ) ) { 502 502 // growing: copy from old to new 503 char * dest = VbyteAlloc( * s.Handle.ulink, origEditSetLength + delta );503 char * dest = VbyteAlloc( *this.Handle.ulink, origEditSetLength + delta ); 504 504 char *destCursor = dest; memcpy(destCursor, prefixStartOrig, prefixLen); 505 505 destCursor += prefixLen; memcpy(destCursor, buffer , bsize ); 506 506 destCursor += bsize; memcpy(destCursor, suffixStartOrig, suffixLen); 507 assignEditSet( s, shareEditSetStartPeer, shareEditSetEndPeer,507 assignEditSet(this, shareEditSetStartPeer, shareEditSetEndPeer, 508 508 dest, 509 509 origEditSetLength + delta, … … 513 513 // room is already allocated in-place: bubble suffix and overwite middle 514 514 memmove( suffixStartOrig + delta, suffixStartOrig, suffixLen ); 515 memcpy( s.Handle.s, buffer, bsize );516 517 assignEditSet( s, shareEditSetStartPeer, shareEditSetEndPeer,515 memcpy( this.Handle.s, buffer, bsize ); 516 517 assignEditSet(this, shareEditSetStartPeer, shareEditSetEndPeer, 518 518 shareEditSetStartPeer->Handle.s, 519 519 origEditSetLength + delta, … … 522 522 523 523 } else if ( // assigning to shared context 524 s.Handle.lnth == origEditSetLength && // overwriting entire run of SES524 this.Handle.lnth == origEditSetLength && // overwriting entire run of SES 525 525 & valSrc && // sourcing from a managed string 526 valSrc.Handle.ulink == s.Handle.ulink ) { // sourcing from same heap526 valSrc.Handle.ulink == this.Handle.ulink ) { // sourcing from same heap 527 527 528 528 // SES's result will only use characters from the source string => reuse source 529 assignEditSet( s, shareEditSetStartPeer, shareEditSetEndPeer,529 assignEditSet(this, shareEditSetStartPeer, shareEditSetEndPeer, 530 530 valSrc.Handle.s, 531 531 valSrc.Handle.lnth, … … 537 537 538 538 // full string is from start of shareEditSetStartPeer thru end of shareEditSetEndPeer 539 // ` s` occurs in the middle of it, to be replaced539 // `this` occurs in the middle of it, to be replaced 540 540 // build up the new text in `pasting` 541 541 542 542 string_res pasting = { 543 * s.Handle.ulink, // maintain same heap, regardless of context543 * this.Handle.ulink, // maintain same heap, regardless of context 544 544 shareEditSetStartPeer->Handle.s, // start of SES 545 s.Handle.s - shareEditSetStartPeer->Handle.s }; // length of SES, befores545 this.Handle.s - shareEditSetStartPeer->Handle.s }; // length of SES, before this 546 546 append( pasting, 547 buffer, // start of replacement for s548 bsize ); // length of replacement for s547 buffer, // start of replacement for this 548 bsize ); // length of replacement for this 549 549 append( pasting, 550 s.Handle.s + s.Handle.lnth, // start of SES afters550 this.Handle.s + this.Handle.lnth, // start of SES after this 551 551 shareEditSetEndPeer->Handle.s + shareEditSetEndPeer->Handle.lnth - 552 ( s.Handle.s + s.Handle.lnth) ); // length of SES, afters552 (this.Handle.s + this.Handle.lnth) ); // length of SES, after this 553 553 554 554 // The above string building can trigger compaction. 555 555 // The reference points (that are arguments of the string building) may move during that building. 556 // From s point on, they are stable.557 558 assignEditSet( s, shareEditSetStartPeer, shareEditSetEndPeer,556 // From this point on, they are stable. 557 558 assignEditSet(this, shareEditSetStartPeer, shareEditSetEndPeer, 559 559 pasting.Handle.s, 560 560 pasting.Handle.lnth, … … 562 562 } 563 563 564 return s; 565 } 566 567 string_res & assign(string_res & s, const string_res & src, size_t maxlen) { 568 return assign_(s, src.Handle.s, min(src.Handle.lnth, maxlen), *0p); 569 } 570 571 string_res & assign(string_res & s, const char * buffer, size_t bsize) { 572 return assign_(s, buffer, bsize, *0p); 573 } 574 575 string_res & ?=?(string_res & s, char c) { 576 return assign(s, &c, 1); 564 return this; 565 } 566 567 string_res & assign(string_res &this, const char* buffer, size_t bsize) { 568 return assign_(this, buffer, bsize, *0p); 569 } 570 571 string_res & ?=?(string_res &s, char other) { 572 return assign(s, &other, 1); 577 573 } 578 574 579 575 // Copy assignment operator 580 string_res & ?=?(string_res & s, const string_res & rhs) with(s ) {581 return assign_( s, rhs.Handle.s, rhs.Handle.lnth, rhs);582 } 583 584 string_res & ?=?(string_res & s, string_res & rhs) with(s ) {576 string_res & ?=?(string_res & this, const string_res & rhs) with( this ) { 577 return assign_(this, rhs.Handle.s, rhs.Handle.lnth, rhs); 578 } 579 580 string_res & ?=?(string_res & this, string_res & rhs) with( this ) { 585 581 const string_res & rhs2 = rhs; 586 return s = rhs2;582 return this = rhs2; 587 583 } 588 584 589 585 590 586 // Destructor 591 void ^?{}(string_res & 587 void ^?{}(string_res &s) with(s) { 592 588 // much delegated to implied ^VbyteSM 593 589 … … 607 603 // With unicode support, this may be different from just the byte at the given 608 604 // offset from the start of the string. 609 char ?[?](const string_res & 605 char ?[?](const string_res &s, size_t index) with(s) { 610 606 //TODO: Check if index is valid (no exceptions yet) 611 607 return Handle.s[index]; 612 608 } 613 609 614 void assignAt(const string_res & s, size_t index, char val) { 615 // caution: not tested (not reachable by string-api-coverage interface) 616 // equivalent form at string level is `s[index] = val`, 617 // which uses the overload that returns a length-1 string 618 string_res editZone = { s, SHARE_EDITS, index, 1 }; 610 void assignAt(const string_res &s, size_t index, char val) { 611 string_res editZone = { s, SHARE_EDITS, index, index+1 }; 619 612 assign(editZone, &val, 1); 620 613 } … … 624 617 // Concatenation 625 618 626 void append(string_res & 619 void append(string_res &str1, const char * buffer, size_t bsize) { 627 620 size_t clnth = str1.Handle.lnth + bsize; 628 621 if ( str1.Handle.s + str1.Handle.lnth == buffer ) { // already juxtapose ? … … 642 635 } 643 636 644 void ?+=?(string_res & str1, const string_res &str2) {637 void ?+=?(string_res &str1, const string_res &str2) { 645 638 append( str1, str2.Handle.s, str2.Handle.lnth ); 646 639 } 647 640 648 void append(string_res & str1, const string_res & str2, size_t maxlen) { 649 append( str1, str2.Handle.s, min(str2.Handle.lnth, maxlen) ); 650 } 651 652 void ?+=?(string_res & s, char c) { 653 append( s, & c, 1 ); 654 } 655 void ?+=?(string_res & s, const char * c) { 656 append( s, c, strlen(c) ); 657 } 658 659 /////////////////////////////////////////////////////////////////// 660 // Repetition 661 662 void ?*=?(string_res & s, size_t factor) { 663 string_res s2 = { s, COPY_VALUE }; 664 s = ""; 665 for (factor) s += s2; 666 } 641 void ?+=?(string_res &s, char other) { 642 append( s, &other, 1 ); 643 } 644 645 646 647 667 648 668 649 ////////////////////////////////////////////////////////// 669 650 // Comparisons 670 651 671 int strcmp(const string_res & s1, const string_res &s2) {652 int cmp(const string_res &s1, const string_res &s2) { 672 653 // return 0; 673 654 int ans1 = memcmp(s1.Handle.s, s2.Handle.s, min(s1.Handle.lnth, s2.Handle.lnth)); … … 676 657 } 677 658 678 bool ?==?(const string_res & s1, const string_res & s2) { return strcmp(s1, s2) == 0; }679 bool ?!=?(const string_res & s1, const string_res & s2) { return strcmp(s1, s2) != 0; }680 bool ?>? (const string_res & s1, const string_res & s2) { return strcmp(s1, s2) > 0; }681 bool ?>=?(const string_res & s1, const string_res & s2) { return strcmp(s1, s2) >= 0; }682 bool ?<=?(const string_res & s1, const string_res & s2) { return strcmp(s1, s2) <= 0; }683 bool ?<? (const string_res & s1, const string_res & s2) { return strcmp(s1, s2) < 0; }684 685 int strcmp (const string_res & s1, const char* s2) {659 bool ?==?(const string_res &s1, const string_res &s2) { return cmp(s1, s2) == 0; } 660 bool ?!=?(const string_res &s1, const string_res &s2) { return cmp(s1, s2) != 0; } 661 bool ?>? (const string_res &s1, const string_res &s2) { return cmp(s1, s2) > 0; } 662 bool ?>=?(const string_res &s1, const string_res &s2) { return cmp(s1, s2) >= 0; } 663 bool ?<=?(const string_res &s1, const string_res &s2) { return cmp(s1, s2) <= 0; } 664 bool ?<? (const string_res &s1, const string_res &s2) { return cmp(s1, s2) < 0; } 665 666 int cmp (const string_res &s1, const char* s2) { 686 667 string_res s2x = s2; 687 return strcmp(s1, s2x);688 } 689 690 bool ?==?(const string_res & s1, const char * s2) { return strcmp(s1, s2) == 0; }691 bool ?!=?(const string_res & s1, const char * s2) { return strcmp(s1, s2) != 0; }692 bool ?>? (const string_res & s1, const char * s2) { return strcmp(s1, s2) > 0; }693 bool ?>=?(const string_res & s1, const char * s2) { return strcmp(s1, s2) >= 0; }694 bool ?<=?(const string_res & s1, const char * s2) { return strcmp(s1, s2) <= 0; }695 bool ?<? (const string_res & s1, const char * s2) { return strcmp(s1, s2) < 0; }696 697 int strcmp (const char* s1, const string_res & s2) {668 return cmp(s1, s2x); 669 } 670 671 bool ?==?(const string_res &s1, const char* s2) { return cmp(s1, s2) == 0; } 672 bool ?!=?(const string_res &s1, const char* s2) { return cmp(s1, s2) != 0; } 673 bool ?>? (const string_res &s1, const char* s2) { return cmp(s1, s2) > 0; } 674 bool ?>=?(const string_res &s1, const char* s2) { return cmp(s1, s2) >= 0; } 675 bool ?<=?(const string_res &s1, const char* s2) { return cmp(s1, s2) <= 0; } 676 bool ?<? (const string_res &s1, const char* s2) { return cmp(s1, s2) < 0; } 677 678 int cmp (const char* s1, const string_res & s2) { 698 679 string_res s1x = s1; 699 return strcmp(s1x, s2);700 } 701 702 bool ?==?(const char * s1, const string_res & s2) { return strcmp(s1, s2) == 0; }703 bool ?!=?(const char * s1, const string_res & s2) { return strcmp(s1, s2) != 0; }704 bool ?>? (const char * s1, const string_res & s2) { return strcmp(s1, s2) > 0; }705 bool ?>=?(const char * s1, const string_res & s2) { return strcmp(s1, s2) >= 0; }706 bool ?<=?(const char * s1, const string_res & s2) { return strcmp(s1, s2) <= 0; }707 bool ?<? (const char * s1, const string_res & s2) { return strcmp(s1, s2) < 0; }680 return cmp(s1x, s2); 681 } 682 683 bool ?==?(const char* s1, const string_res &s2) { return cmp(s1, s2) == 0; } 684 bool ?!=?(const char* s1, const string_res &s2) { return cmp(s1, s2) != 0; } 685 bool ?>? (const char* s1, const string_res &s2) { return cmp(s1, s2) > 0; } 686 bool ?>=?(const char* s1, const string_res &s2) { return cmp(s1, s2) >= 0; } 687 bool ?<=?(const char* s1, const string_res &s2) { return cmp(s1, s2) <= 0; } 688 bool ?<? (const char* s1, const string_res &s2) { return cmp(s1, s2) < 0; } 708 689 709 690 … … 712 693 // Search 713 694 714 bool contains(const string_res & 695 bool contains(const string_res &s, char ch) { 715 696 for ( i; size(s) ) { 716 697 if (s[i] == ch) return true; … … 719 700 } 720 701 721 int find(const string_res & 702 int find(const string_res &s, char search) { 722 703 return findFrom(s, 0, search); 723 704 } 724 705 725 int findFrom(const string_res & 706 int findFrom(const string_res &s, size_t fromPos, char search) { 726 707 // FIXME: This paricular overload (find of single char) is optimized to use memchr. 727 708 // The general overload (find of string, memchr applying to its first character) and `contains` should be adjusted to match. … … 734 715 } 735 716 736 int find(const string_res & s, const string_res &search) {717 int find(const string_res &s, const string_res &search) { 737 718 return findFrom(s, 0, search); 738 719 } 739 720 740 int findFrom(const string_res & s, size_t fromPos, const string_res &search) {721 int findFrom(const string_res &s, size_t fromPos, const string_res &search) { 741 722 return findFrom(s, fromPos, search.Handle.s, search.Handle.lnth); 742 723 } 743 724 744 int find(const string_res & s, const char* search) {725 int find(const string_res &s, const char* search) { 745 726 return findFrom(s, 0, search); 746 727 } 747 int findFrom(const string_res & s, size_t fromPos, const char* search) {728 int findFrom(const string_res &s, size_t fromPos, const char* search) { 748 729 return findFrom(s, fromPos, search, strlen(search)); 749 730 } 750 731 751 int find(const string_res & s, const char* search, size_t searchsize) {732 int find(const string_res &s, const char* search, size_t searchsize) { 752 733 return findFrom(s, 0, search, searchsize); 753 734 } 754 735 755 int findFrom(const string_res & s, size_t fromPos, const char* search, size_t searchsize) {736 int findFrom(const string_res &s, size_t fromPos, const char* search, size_t searchsize) { 756 737 757 738 /* Remaining implementations essentially ported from Sunjay's work */ … … 790 771 } 791 772 792 bool includes(const string_res & s, const string_res &search) {773 bool includes(const string_res &s, const string_res &search) { 793 774 return includes(s, search.Handle.s, search.Handle.lnth); 794 775 } 795 776 796 bool includes(const string_res & s, const char* search) {777 bool includes(const string_res &s, const char* search) { 797 778 return includes(s, search, strlen(search)); 798 779 } 799 780 800 bool includes(const string_res & s, const char* search, size_t searchsize) {781 bool includes(const string_res &s, const char* search, size_t searchsize) { 801 782 return find(s, search, searchsize) < s.Handle.lnth; 802 783 } 803 784 804 bool startsWith(const string_res & s, const string_res &prefix) {785 bool startsWith(const string_res &s, const string_res &prefix) { 805 786 return startsWith(s, prefix.Handle.s, prefix.Handle.lnth); 806 787 } 807 788 808 bool startsWith(const string_res & s, const char* prefix) {789 bool startsWith(const string_res &s, const char* prefix) { 809 790 return startsWith(s, prefix, strlen(prefix)); 810 791 } 811 792 812 bool startsWith(const string_res & s, const char* prefix, size_t prefixsize) {793 bool startsWith(const string_res &s, const char* prefix, size_t prefixsize) { 813 794 if (s.Handle.lnth < prefixsize) { 814 795 return false; … … 817 798 } 818 799 819 bool endsWith(const string_res & s, const string_res &suffix) {800 bool endsWith(const string_res &s, const string_res &suffix) { 820 801 return endsWith(s, suffix.Handle.s, suffix.Handle.lnth); 821 802 } 822 803 823 bool endsWith(const string_res & s, const char* suffix) {804 bool endsWith(const string_res &s, const char* suffix) { 824 805 return endsWith(s, suffix, strlen(suffix)); 825 806 } 826 807 827 bool endsWith(const string_res & s, const char* suffix, size_t suffixsize) {808 bool endsWith(const string_res &s, const char* suffix, size_t suffixsize) { 828 809 if (s.Handle.lnth < suffixsize) { 829 810 return false; … … 841 822 // charclass, include, exclude 842 823 843 void ?{}( charclass_res & s, const string_res & chars) {844 ( s){ chars.Handle.s, chars.Handle.lnth };845 } 846 847 void ?{}( charclass_res & s, const char * chars ) {848 ( s){ chars, strlen(chars) };849 } 850 851 void ?{}( charclass_res & s, const char * chars, size_t charssize ) {852 ( s.chars){ chars, charssize };824 void ?{}( charclass_res & this, const string_res & chars) { 825 (this){ chars.Handle.s, chars.Handle.lnth }; 826 } 827 828 void ?{}( charclass_res & this, const char * chars ) { 829 (this){ chars, strlen(chars) }; 830 } 831 832 void ?{}( charclass_res & this, const char * chars, size_t charssize ) { 833 (this.chars){ chars, charssize }; 853 834 // now sort it ? 854 835 } 855 836 856 void ^?{}( charclass_res & s ) {857 ^( s.chars){};837 void ^?{}( charclass_res & this ) { 838 ^(this.chars){}; 858 839 } 859 840 … … 863 844 } 864 845 865 int exclude(const string_res & s, const charclass_res &mask) {846 int exclude(const string_res &s, const charclass_res &mask) { 866 847 for ( i; size(s) ) { 867 848 if ( test(mask, s[i]) ) return i; … … 870 851 } 871 852 872 int include(const string_res & s, const charclass_res &mask) {853 int include(const string_res &s, const charclass_res &mask) { 873 854 for ( i; size(s) ) { 874 855 if ( ! test(mask, s[i]) ) return i; … … 882 863 // Add a new HandleNode node n after the current HandleNode node. 883 864 884 static void AddThisAfter( HandleNode & s, HandleNode & n ) with(s) {885 #ifdef VbyteDebug 886 serr | "enter:AddThisAfter, s:" | &s | " n:" | &n;865 static void AddThisAfter( HandleNode & this, HandleNode & n ) with(this) { 866 #ifdef VbyteDebug 867 serr | "enter:AddThisAfter, this:" | &this | " n:" | &n; 887 868 #endif // VbyteDebug 888 869 // Performance note: we are on the critical path here. MB has ensured that the verifies don't contribute to runtime (are compiled away, like they're supposed to be). 889 870 verify( n.ulink != 0p ); 890 verify( s.ulink == n.ulink );871 verify( this.ulink == n.ulink ); 891 872 flink = n.flink; 892 873 blink = &n; 893 n.flink->blink = & s;894 n.flink = & s;874 n.flink->blink = &this; 875 n.flink = &this; 895 876 #ifdef VbyteDebug 896 877 { … … 913 894 // Delete the current HandleNode node. 914 895 915 static void DeleteNode( HandleNode & s ) with(s) {916 #ifdef VbyteDebug 917 serr | "enter:DeleteNode, s:" | &s;896 static void DeleteNode( HandleNode & this ) with(this) { 897 #ifdef VbyteDebug 898 serr | "enter:DeleteNode, this:" | &this; 918 899 #endif // VbyteDebug 919 900 flink->blink = blink; … … 925 906 926 907 908 927 909 // Allocates specified storage for a string from byte-string area. If not enough space remains to perform the 928 910 // allocation, the garbage collection routine is called. 929 911 930 static char * VbyteAlloc( VbyteHeap & s, int size ) with(s) {912 static char * VbyteAlloc( VbyteHeap & this, int size ) with(this) { 931 913 #ifdef VbyteDebug 932 914 serr | "enter:VbyteAlloc, size:" | size; … … 936 918 937 919 NoBytes = ( uintptr_t )EndVbyte + size; 938 if ( NoBytes > ( uintptr_t )ExtVbyte ) { 939 garbage( s, size );// firer up the garbage collector920 if ( NoBytes > ( uintptr_t )ExtVbyte ) { // enough room for new byte-string ? 921 garbage( this, size ); // firer up the garbage collector 940 922 verify( (( uintptr_t )EndVbyte + size) <= ( uintptr_t )ExtVbyte && "garbage run did not free up required space" ); 941 923 } // if … … 957 939 // VbyteAlloc to claim the new space, while doing optimal copying from old to new, then free old. 958 940 959 static char * VbyteTryAdjustLast( VbyteHeap & s, int delta ) with(s) { 941 static char * VbyteTryAdjustLast( VbyteHeap & this, int delta ) with(this) { 942 960 943 if ( ( uintptr_t )EndVbyte + delta <= ( uintptr_t )ExtVbyte ) { 961 944 // room available … … 978 961 // the address in the byte string area. 979 962 980 static void MoveThisAfter( HandleNode & s, const HandleNode & h ) with(s) {981 #ifdef VbyteDebug 982 serr | "enter:MoveThisAfter, s:" | &s | " h:" | & h;963 static void MoveThisAfter( HandleNode & this, const HandleNode & h ) with(this) { 964 #ifdef VbyteDebug 965 serr | "enter:MoveThisAfter, this:" | & this | " h:" | & h; 983 966 #endif // VbyteDebug 984 967 verify( h.ulink != 0p ); 985 verify( s.ulink == h.ulink );968 verify( this.ulink == h.ulink ); 986 969 if ( s < h.s ) { // check argument values 987 970 // serr | "VbyteSM: Error - Cannot move byte string starting at:" | s | " after byte string starting at:" … … 993 976 HandleNode *i; 994 977 for ( i = h.flink; i->s != 0 && s > ( i->s ); i = i->flink ); // find the position for this node after h 995 if ( & s != i->blink ) {996 DeleteNode( s );997 AddThisAfter( s, *i->blink );978 if ( & this != i->blink ) { 979 DeleteNode( this ); 980 AddThisAfter( this, *i->blink ); 998 981 } // if 999 982 #ifdef VbyteDebug … … 1075 1058 // the containing string has been moved. Hence, they only require that their string pointers be adjusted. 1076 1059 1077 void compaction(VbyteHeap & s) with(s) {1060 void compaction(VbyteHeap & this) with(this) { 1078 1061 HandleNode *h; 1079 1062 char *obase, *nbase, *limit; … … 1115 1098 // the heap. The heap is then compacted in the existing heap or into the newly allocated heap. 1116 1099 1117 void garbage(VbyteHeap & s, int minreq ) with(s) {1100 void garbage(VbyteHeap & this, int minreq ) with(this) { 1118 1101 #ifdef VbyteDebug 1119 1102 serr | "enter:garbage"; … … 1141 1124 if ( ( double ) AmountFree < ( CurrSize * heap_expansion_freespace_threshold ) || AmountFree < minreq ) { // free space less than threshold or not enough to serve cur request 1142 1125 1143 extend( s, max( CurrSize, minreq ) ); // extend the heap1126 extend( this, max( CurrSize, minreq ) ); // extend the heap 1144 1127 1145 1128 // Peter says, "This needs work before it should be used." … … 1150 1133 1151 1134 } else { 1152 compaction( s); // in-place1135 compaction(this); // in-place 1153 1136 }// if 1154 1137 #ifdef VbyteDebug … … 1176 1159 // area is deleted. 1177 1160 1178 void extend( VbyteHeap & s, int size ) with (s) {1161 void extend( VbyteHeap & this, int size ) with (this) { 1179 1162 #ifdef VbyteDebug 1180 1163 serr | "enter:extend, size:" | size; … … 1188 1171 StartVbyte = EndVbyte = TEMP_ALLOC(char, CurrSize); 1189 1172 ExtVbyte = (void *)( StartVbyte + CurrSize ); 1190 compaction( s); // copy from old heap to new & adjust pointers to new heap1173 compaction(this); // copy from old heap to new & adjust pointers to new heap 1191 1174 free( OldStartVbyte ); // release old heap 1192 1175 #ifdef VbyteDebug -
libcfa/src/collections/string_res.hfa
rf988834 r59c8dff 10 10 // Created On : Fri Sep 03 11:00:00 2021 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Jan 4 11:28:06 202413 // Update Count : 2 712 // Last Modified On : Sat Aug 12 15:45:47 2023 13 // Update Count : 2 14 14 // 15 15 … … 70 70 71 71 // Getters 72 size_t size(const string_res & 72 size_t size(const string_res &s); 73 73 74 74 // Constructors, Assignment Operators, Destructor 75 void ?{}(string_res & 76 void ?{}(string_res & s, const char* buffer, size_t bsize); // copy specific length from buffer77 static inline void ?{}(string_res & s, const char* rhs) { // copy from string literal (NULL-terminated)75 void ?{}(string_res &s); // empty string 76 void ?{}(string_res &s, const char* buffer, size_t bsize); // copy specific length from buffer 77 static inline void ?{}(string_res &s, const char* rhs) { // copy from string literal (NULL-terminated) 78 78 (s){ rhs, strlen(rhs) }; 79 79 } 80 static inline void ?{}(string_res & s, char c ) { 81 ?{}( s, &c, 1); 82 } 83 84 // Deleting the copy constructors makes the compiler reject an attempt to call/return by value 85 void ?{}(string_res & s, const string_res & s2) = void; 86 void ?{}(string_res & s, string_res & s2) = void; 80 81 void ?{}(string_res &s, const string_res & s2) = void; 82 void ?{}(string_res &s, string_res & s2) = void; 87 83 88 84 enum StrResInitMode { COPY_VALUE, SHARE_EDITS }; 89 void ?{}(string_res & s, const string_res & src, StrResInitMode, size_t start, size_t len);90 static inline void ?{}(string_res & 85 void ?{}(string_res &s, const string_res & src, StrResInitMode, size_t start, size_t end ); 86 static inline void ?{}(string_res &s, const string_res & src, StrResInitMode mode ) { 91 87 ?{}( s, src, mode, 0, size(src)); 92 88 } 93 static inline void ?{}(string_res & s, const string_res & src, StrResInitMode mode, size_t maxlen ) { 94 ?{}( s, src, mode, 0, (size(src) > maxlen)?maxlen:size(src) ); 95 } 96 97 string_res & assign(string_res & s, const string_res & src, size_t maxlen); // copy specific length from other string 98 string_res & assign(string_res & s, const char * buffer, size_t bsize); // copy specific length from buffer 99 static inline string_res & ?=?(string_res & s, const char * c) { // copy from string literal (NULL-terminated) 100 return assign(s, c, strlen(c)); 101 } 102 string_res & ?=?(string_res & s, const string_res & c); 103 string_res & ?=?(string_res & s, string_res & c); 104 string_res & ?=?(string_res & s, char c); 105 106 void ^?{}(string_res & s); 89 90 string_res & assign(string_res &s, const char* buffer, size_t bsize); // copy specific length from buffer 91 static inline string_res & ?=?(string_res &s, const char* other) { // copy from string literal (NULL-terminated) 92 return assign(s, other, strlen(other)); 93 } 94 string_res & ?=?(string_res &s, const string_res &other); 95 string_res & ?=?(string_res &s, string_res &other); 96 string_res & ?=?(string_res &s, char other); 97 98 void ^?{}(string_res &s); 107 99 108 100 // IO Operator 109 ofstream & ?|?(ofstream & out, const string_res &s);110 void ?|?(ofstream & out, const string_res &s);111 ifstream & ?|?(ifstream & in, string_res &s);112 void ?|?( ifstream & in, string_res & s );101 ofstream & ?|?(ofstream &out, const string_res &s); 102 void ?|?(ofstream &out, const string_res &s); 103 ifstream & ?|?(ifstream &in, string_res &s); 104 void ?|?( ifstream & in, string_res & this ); 113 105 114 106 struct _Istream_Rstr { … … 121 113 _Istream_Rstr wdi( unsigned int rwd, string_res & s ) { return (_Istream_Rstr)@{ &s, {{0p}, rwd, {.flags.rwd : true}} }; } 122 114 _Istream_Rstr getline( string_res & s, const char delimiter = '\n' ) { 123 return (_Istream_Rstr)@{ &s, {{.delimiter s: { delimiter, '\0' } }, -1, {.flags.delimiter : true, .flags.inex : true}} };115 return (_Istream_Rstr)@{ &s, {{.delimiter : { delimiter, '\0' } }, -1, {.flags.delimiter : true, .flags.inex : true}} }; 124 116 } 125 117 _Istream_Rstr & getline( _Istream_Rstr & fmt, const char delimiter = '\n' ) { 126 fmt.delimiter s[0] = delimiter; fmt.delimiters[1] = '\0'; fmt.flags.delimiter = true; fmt.flags.inex = true; return fmt;118 fmt.delimiter[0] = delimiter; fmt.delimiter[1] = '\0'; fmt.flags.delimiter = true; fmt.flags.inex = true; return fmt; 127 119 } 128 120 _Istream_Rstr incl( const char scanset[], string_res & s ) { return (_Istream_Rstr)@{ &s, {{scanset}, -1, {.flags.inex : false}} }; } … … 137 129 138 130 // Concatenation 139 void ?+=?(string_res & s, const string_res & s2); 140 void ?+=?(string_res & s, char c); 141 void append(string_res & s, const string_res & s2, size_t maxlen); 142 void ?+=?(string_res & s, const char * c); 143 void append(string_res & s, const char * buffer, size_t bsize); 144 145 static inline string_res & strcat(string_res & s, const string_res & s2) { s += s2; return s; } 146 static inline string_res & strcat(string_res & s, const char * c) { s += c; return s; } 147 static inline string_res & strncat(string_res & s, const string_res & s2, size_t maxlen) { append(s, s2, maxlen); return s; } 148 static inline string_res & strncat(string_res & s, const char * buffer, size_t bsize) { append(s, buffer, bsize); return s; } 149 150 // Repetition 151 void ?*=?(string_res & s, size_t factor); 131 void append(string_res &s, const char* buffer, size_t bsize); 132 void ?+=?(string_res &s, char other); // append a character 133 void ?+=?(string_res &s, const string_res &s2); // append-concatenate to first string 134 static inline void ?+=?(string_res &s, const char* other) { 135 append( s, other, strlen(other) ); 136 } 152 137 153 138 // Character access 154 void assignAt(const string_res & 155 char ?[?](const string_res & 156 //char codePointAt(const string_res & 139 void assignAt(const string_res &s, size_t index, char val); 140 char ?[?](const string_res &s, size_t index); // Mike changed to ret by val from Sunjay's ref, to match Peter's 141 //char codePointAt(const string_res &s, size_t index); // revisit under Unicode 157 142 158 143 // Comparisons 159 int strcmp (const string_res &, const string_res &);144 int cmp (const string_res &, const string_res &); 160 145 bool ?==?(const string_res &, const string_res &); 161 146 bool ?!=?(const string_res &, const string_res &); … … 165 150 bool ?<? (const string_res &, const string_res &); 166 151 167 int strcmp(const string_res &, const char*);168 bool ?==?(const string_res &, const char 169 bool ?!=?(const string_res &, const char 170 bool ?>? (const string_res &, const char 171 bool ?>=?(const string_res &, const char 172 bool ?<=?(const string_res &, const char 173 bool ?<? (const string_res &, const char 174 175 int strcmp(const char*, const string_res &);176 bool ?==?(const char 177 bool ?!=?(const char 178 bool ?>? (const char 179 bool ?>=?(const char 180 bool ?<=?(const char 181 bool ?<? (const char 152 int cmp (const string_res &, const char*); 153 bool ?==?(const string_res &, const char*); 154 bool ?!=?(const string_res &, const char*); 155 bool ?>? (const string_res &, const char*); 156 bool ?>=?(const string_res &, const char*); 157 bool ?<=?(const string_res &, const char*); 158 bool ?<? (const string_res &, const char*); 159 160 int cmp (const char*, const string_res &); 161 bool ?==?(const char*, const string_res &); 162 bool ?!=?(const char*, const string_res &); 163 bool ?>? (const char*, const string_res &); 164 bool ?>=?(const char*, const string_res &); 165 bool ?<=?(const char*, const string_res &); 166 bool ?<? (const char*, const string_res &); 182 167 183 168 // String search 184 bool contains(const string_res & 185 186 int find(const string_res & 187 int find(const string_res & s, const string_res &search);188 int find(const string_res & s, const char* search);189 int find(const string_res & s, const char* search, size_t searchsize);190 191 int findFrom(const string_res & 192 int findFrom(const string_res & s, size_t fromPos, const string_res &search);193 int findFrom(const string_res & s, size_t fromPos, const char* search);194 int findFrom(const string_res & s, size_t fromPos, const char* search, size_t searchsize);195 196 bool includes(const string_res & s, const string_res &search);197 bool includes(const string_res & s, const char* search);198 bool includes(const string_res & s, const char* search, size_t searchsize);199 200 bool startsWith(const string_res & s, const string_res &prefix);201 bool startsWith(const string_res & s, const char* prefix);202 bool startsWith(const string_res & s, const char* prefix, size_t prefixsize);203 204 bool endsWith(const string_res & s, const string_res &suffix);205 bool endsWith(const string_res & s, const char* suffix);206 bool endsWith(const string_res & s, const char* suffix, size_t suffixsize);207 208 int include(const string_res & s, const charclass_res &mask);209 int exclude(const string_res & s, const charclass_res &mask);169 bool contains(const string_res &s, char ch); // single character 170 171 int find(const string_res &s, char search); 172 int find(const string_res &s, const string_res &search); 173 int find(const string_res &s, const char* search); 174 int find(const string_res &s, const char* search, size_t searchsize); 175 176 int findFrom(const string_res &s, size_t fromPos, char search); 177 int findFrom(const string_res &s, size_t fromPos, const string_res &search); 178 int findFrom(const string_res &s, size_t fromPos, const char* search); 179 int findFrom(const string_res &s, size_t fromPos, const char* search, size_t searchsize); 180 181 bool includes(const string_res &s, const string_res &search); 182 bool includes(const string_res &s, const char* search); 183 bool includes(const string_res &s, const char* search, size_t searchsize); 184 185 bool startsWith(const string_res &s, const string_res &prefix); 186 bool startsWith(const string_res &s, const char* prefix); 187 bool startsWith(const string_res &s, const char* prefix, size_t prefixsize); 188 189 bool endsWith(const string_res &s, const string_res &suffix); 190 bool endsWith(const string_res &s, const char* suffix); 191 bool endsWith(const string_res &s, const char* suffix, size_t suffixsize); 192 193 int include(const string_res &s, const charclass_res &mask); 194 int exclude(const string_res &s, const charclass_res &mask); 210 195 211 196 // Modifiers 212 void padStart(string_res & 213 void padStart(string_res & 214 void padEnd(string_res & 197 void padStart(string_res &s, size_t n); 198 void padStart(string_res &s, size_t n, char padding); 199 void padEnd(string_res &s, size_t n); 215 200 void padEnd(string_res &s, size_t n, char padding); 216 201 -
libcfa/src/heap.cfa
rf988834 r59c8dff 10 10 // Created On : Tue Dec 19 21:58:35 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Jan 3 21:30:54 202413 // Update Count : 161 912 // Last Modified On : Sat Sep 30 17:31:15 2023 13 // Update Count : 1617 14 14 // 15 15 … … 27 27 #include "bits/align.hfa" // libAlign 28 28 #include "bits/defs.hfa" // likely, unlikely 29 #include "concurrency/kernel/fwd.hfa" // disable_interrupts, enable_interrupts29 #include "concurrency/kernel/fwd.hfa" // __POLL_PREEMPTION 30 30 #include "startup.hfa" // STARTUP_PRIORITY_MEMORY 31 31 #include "math.hfa" // ceiling, min -
libcfa/src/interpose.cfa
rf988834 r59c8dff 10 10 // Created On : Wed Mar 29 16:10:31 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Jan 11 18:45:31 202413 // Update Count : 21812 // Last Modified On : Mon Mar 27 21:09:03 2023 13 // Update Count : 196 14 14 // 15 15 … … 18 18 extern "C" { 19 19 #include <dlfcn.h> // dlopen, dlsym 20 //#include <link.h> // dl_iterate_phdr21 struct dl_phdr_info;22 int dl_iterate_phdr( int (*)( struct dl_phdr_info *, size_t, void * ), void * );23 20 #include <execinfo.h> // backtrace, messages 24 21 } … … 26 23 #include "bits/defs.hfa" 27 24 #include "bits/signal.hfa" // sigHandler_? 28 #include "concurrency/kernel/fwd.hfa" // disable_interrupts, enable_interrupts29 25 #include "startup.hfa" // STARTUP_PRIORITY_CORE 30 26 #include <assert.h> … … 91 87 void (* exit)( int ) __attribute__(( __noreturn__ )); 92 88 void (* abort)( void ) __attribute__(( __noreturn__ )); 93 int (* dl_iterate_phdr)( int (*)( struct dl_phdr_info *, size_t, void * ), void * );94 89 } __cabi_libc; 95 90 … … 107 102 #pragma GCC diagnostic ignored "-Wdiscarded-qualifiers" 108 103 INTERPOSE_LIBC( abort, version ); 109 INTERPOSE_LIBC( exit, version ); 110 INTERPOSE_LIBC( dl_iterate_phdr, version ); 104 INTERPOSE_LIBC( exit , version ); 111 105 #pragma GCC diagnostic pop 112 106 … … 156 150 } 157 151 } 158 159 extern "C" int dl_iterate_phdr( int (* callback)( struct dl_phdr_info *, size_t, void * ), void * data ) {160 disable_interrupts();161 int ret = __cabi_libc.dl_iterate_phdr( callback, data ); // call real routine162 enable_interrupts( false );163 return ret;164 } // dl_iterate_phdr165 152 166 153 //============================================================================================= -
libcfa/src/iostream.cfa
rf988834 r59c8dff 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Jan 3 10:53:13 202413 // Update Count : 18 9812 // Last Modified On : Fri Nov 17 13:33:12 2023 13 // Update Count : 1853 14 14 // 15 15 … … 984 984 } 985 985 986 istype & ?|?( istype & is, _Istream_Cquoted f ) with( f ){986 istype & ?|?( istype & is, _Istream_Cquoted f ) { 987 987 char fmtstr[32]; // storage scanset and format codes 988 988 fmtstr[0] = '%'; … … 992 992 bool check = true; 993 993 994 if ( cstr.flags.ignore ) { check = false; fmtstr[1] = '*'; pos += 1; }995 int rwd = cstr.wd;996 if ( cstr.wd != -1 ) {// => just ignore versus ignore with width994 if ( f.flags.ignore ) { check = false; fmtstr[1] = '*'; pos += 1; } 995 int rwd = f.wd; 996 if ( f.wd != -1 ) { // => just ignore versus ignore with width 997 997 // wd is buffer bytes available (for input chars + null terminator) 998 998 // rwd is count of input chars 999 999 // no maximum width necessary because text ignored => width is read width 1000 if ( cstr.flags.rwd ) check = false;1001 else rwd = cstr.wd - 1;1000 if ( f.flags.rwd ) check = false; 1001 else rwd = f.wd - 1; 1002 1002 pos += sprintf( &fmtstr[pos], "%d", rwd ); 1003 1003 } // if 1004 1004 1005 1005 int len = 0; // may not be set in fmt 1006 char enddelim;1007 if ( ! cstr.flags.inex ) { // => quoted getline1006 if ( ! f.flags.inex ) { // => quoted getline 1007 // fprintf( stderr, "quoted\n" ); 1008 1008 args = fmt( is, "%*[ \f\n\r\t\v]" ); // remove leading whitespace 1009 1009 if ( eof( is ) ) goto Eof; 1010 char rfmt[4] = { cstr.delimiters[0], '%', 'n', '\0' }; 1011 args = fmt( is, rfmt, &len ); // remove leading quote 1010 // args = fmt( is, (const char *)f.delimiter ); // remove leading quote 1011 args = fmt( is, "'%n", &len ); // remove leading quote 1012 fprintf( stderr, "quoted %d %d\n", args, len ); 1012 1013 if ( len == 0 || eof( is ) ) goto Eof; 1013 1014 } // if 1014 enddelim = cstr.delimiters[1] == '\0' ? cstr.delimiters[0] : cstr.delimiters[1]; 1015 sprintf( &fmtstr[pos], "[^%c]%%n", enddelim ); 1016 if ( cstr.flags.ignore ) args = fmt( is, fmtstr, &len ); // no string argument for '*' 1017 else args = fmt( is, fmtstr, cstr.s, &len ); 1015 sprintf( &fmtstr[pos], "[^%c]%%n", f.delimiter[0] ); 1016 // fprintf( stderr, "getline %s %d\n", fmtstr, f.wd ); 1017 if ( f.flags.ignore ) args = fmt( is, fmtstr, &len ); // no string argument for '*' 1018 else args = fmt( is, fmtstr, f.s, &len ); 1019 // fprintf( stderr, "getline %s %d %d %d\n", fmtstr, args, f.wd, eof( is ) ); 1018 1020 if ( check && len == rwd && ! eof( is ) ) { // might not fit 1019 1021 char peek; 1020 1022 fmt( is, "%c", &peek ); // check for delimiter 1023 // fprintf( stderr, "peek %d '%c'\n", args, peek ); 1021 1024 if ( ! eof( is ) ) { 1022 if ( peek != enddelim) {1025 if ( peek != f.delimiter[0] ) { 1023 1026 ungetc( is, peek ); 1024 1027 throwResume ExceptionInst( cstring_length ); … … 1027 1030 } else fmt( is, "%*c" ); // remove delimiter 1028 1031 Eof: ; 1029 if ( rwd > 0 && args == 0 ) cstr.s[0] = '\0';// read failed => no pattern match => set string to null1032 if ( rwd > 0 && args == 0 ) f.s[0] = '\0'; // read failed => no pattern match => set string to null 1030 1033 if ( args == 1 && eof( is ) ) { // data but scan ended at EOF 1034 // fprintf( stderr, "clear\n" ); 1031 1035 clear( is ); // => reset EOF => detect again on next read 1032 1036 } // if … … 1034 1038 } 1035 1039 1036 istype & ?|?( istype & is, _Istream_Cstr f ) with( f ){1040 istype & ?|?( istype & is, _Istream_Cstr f ) { 1037 1041 const char * scanset; 1038 1042 size_t nscanset = 0; 1039 if ( f lags.delimiter ) scanset = delimiters; // getline ?1043 if ( f.flags.delimiter ) scanset = f.delimiter; // getline ? 1040 1044 else scanset = f.scanset; 1041 1045 if ( scanset ) nscanset = strlen( scanset ); … … 1080 1084 if ( f.flags.delimiter ) { // getline 1081 1085 int len = 0; // may not be set in fmt 1082 sprintf( &fmtstr[pos], "[^%c]%%n", f.delimiters[0] ); 1086 if ( ! f.flags.inex ) { // => quoted getline 1087 // fprintf( stderr, "quoted\n" ); 1088 args = fmt( is, "%*[ \f\n\r\t\v]" ); // remove leading whitespace 1089 if ( eof( is ) ) goto X; 1090 args = fmt( is, "\"" ); // remove leading quote 1091 if ( eof( is ) ) goto X; 1092 } // if 1093 // fprintf( stderr, "getline\n" ); 1094 // sprintf( &fmtstr[pos], "[%s%s]%%n", f.flags.inex ? "^" : "", scanset ); 1095 sprintf( &fmtstr[pos], "[^%s]%%n", scanset ); 1096 // fprintf( stderr, "getline %s %d\n", fmtstr, f.wd ); 1083 1097 if ( f.flags.ignore ) args = fmt( is, fmtstr, &len ); // no string argument for '*' 1084 1098 else args = fmt( is, fmtstr, f.s, &len ); 1099 // fprintf( stderr, "getline %s %d %d %d\n", fmtstr, args, f.wd, eof( is ) ); 1085 1100 if ( check && len == rwd && ! eof( is ) ) { // might not fit 1086 fmtstr[0] = f.delimiters[0]; fmtstr[1] = '%'; fmtstr[2] = 'n'; fmtstr[3] = '\0'; 1087 fmt( is, fmtstr, &len ); // remove delimiter 1101 char peek; 1102 fmt( is, "%c", &peek ); // check for delimiter 1103 // fprintf( stderr, "peek %d '%c'\n", args, peek ); 1088 1104 if ( ! eof( is ) ) { 1089 // if ( peek != f.delimiter[0] ) { 1090 if ( len != 1 ) { 1091 // ungetc( is, peek ); 1105 if ( peek != f.delimiter[0] ) { 1106 ungetc( is, peek ); 1092 1107 throwResume ExceptionInst( cstring_length ); 1093 1108 } // if 1094 1109 } // if 1095 } else fmt( is, "%*c" ); // remove delimiter 1110 } else fmt( is, "%*c" ); // remove delimiter 1111 X: ; 1096 1112 } else { 1097 1113 // incl %[xxx], %*[xxx], %w[xxx], %*w[xxx] -
libcfa/src/iostream.hfa
rf988834 r59c8dff 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Jan 3 10:53:18 202413 // Update Count : 61012 // Last Modified On : Wed Nov 15 17:55:31 2023 13 // Update Count : 596 14 14 // 15 15 … … 392 392 union { 393 393 const char * scanset; 394 char delimiter s[3]; // [0] => left, [1] => right394 char delimiter[2]; 395 395 }; 396 396 int wd; // width … … 412 412 413 413 struct _Istream_Cquoted { 414 _Istream_Cstr cstr; 414 char * s; 415 inline _Istream_str_base; 415 416 }; // _Istream_Cquoted 416 417 … … 418 419 // width must include room for null terminator 419 420 _Istream_Cstr wdi( unsigned int wd, char s[] ) { return (_Istream_Cstr)@{ s, { {0p}, wd, {.all : 0} } }; } 421 // read width does not include null terminator 420 422 _Istream_Cstr wdi( unsigned int wd, unsigned int rwd, char s[] ) { 421 423 if ( wd <= rwd ) throw (cstring_length){ &cstring_length_vt }; 422 424 return (_Istream_Cstr)@{ s, { {0p}, rwd, {.flags.rwd : true} } }; 423 425 } 424 _Istream_Cquoted & quoted( _Istream_Cstr & fmt, const char Ldelimiter = '"', const char Rdelimiter = '\0' ) {425 fmt.delimiter s[0] = Ldelimiter; fmt.delimiters[1] = Rdelimiter; fmt.delimiters[2] = '\0';426 _Istream_Cquoted & quoted( _Istream_Cstr & fmt, const char delimiter = '"' ) { 427 fmt.delimiter[0] = delimiter; fmt.delimiter[1] = '\0'; 426 428 return (_Istream_Cquoted &)fmt; 427 429 } 428 430 _Istream_Cstr & getline( _Istream_Cstr & fmt, const char delimiter = '\n' ) { 429 fmt.delimiters[0] = delimiter; fmt.delimiters[1] = '\0'; fmt.flags.delimiter = true; fmt.flags.inex = true; return fmt; 430 } 431 fmt.delimiter[0] = delimiter; fmt.delimiter[1] = '\0'; fmt.flags.delimiter = true; fmt.flags.inex = true; return fmt; } 431 432 _Istream_Cstr & incl( const char scanset[], _Istream_Cstr & fmt ) { fmt.scanset = scanset; fmt.flags.inex = false; return fmt; } 432 433 _Istream_Cstr & excl( const char scanset[], _Istream_Cstr & fmt ) { fmt.scanset = scanset; fmt.flags.inex = true; return fmt; } -
src/AST/Attribute.cpp
rf988834 r59c8dff 38 38 39 39 bool Attribute::isValidOnFuncParam() const { 40 // Attributes produce GCC errors when they appear on function41 // parameters. Names on the previous allow-list implementation:42 // unused, noreturn, __vector_size__40 // attributes such as aligned, cleanup, etc. produce GCC errors when they appear 41 // on function parameters. Maintain here a whitelist of attribute names that are 42 // allowed to appear on parameters. 43 43 std::string norm = normalizedName(); 44 return norm != "aligned" && norm != "packed" && norm != "used";44 return norm == "unused" || norm == "noreturn"; 45 45 } 46 46 -
src/AST/Decl.hpp
rf988834 r59c8dff 29 29 #include "StorageClasses.hpp" 30 30 #include "Visitor.hpp" 31 #include "Common/utility.h" 31 32 32 33 // Must be included in *all* AST classes; should be #undef'd at the end of the file -
src/AST/Pass.proto.hpp
rf988834 r59c8dff 19 19 #include "Common/Iterate.hpp" 20 20 #include "Common/Stats/Heap.h" 21 #include "Common/utility.h"22 21 namespace ast { 23 22 template<typename core_t> class Pass; -
src/CodeGen/CodeGenerator.hpp
rf988834 r59c8dff 21 21 #include "AST/Pass.hpp" // for WithGuards, WithShortCircuiting, ... 22 22 #include "CodeGen/Options.h" // for Options 23 #include "Common/Indenter.h" // for Indenter24 23 25 24 -
src/Common/utility.h
rf988834 r59c8dff 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Jan 17 14:40:00 202413 // Update Count : 5 412 // Last Modified On : Fri Feb 17 15:25:00 2023 13 // Update Count : 53 14 14 // 15 15 … … 17 17 18 18 #include <cassert> 19 #include <cctype> 19 20 #include <algorithm> 21 #include <iostream> 20 22 #include <list> 23 #include <memory> 21 24 #include <string> 22 25 #include <type_traits> 23 26 #include <vector> 27 #include <cstring> // memcmp 28 29 #include "Common/Indenter.h" 30 31 class Expression; 32 33 /// bring std::move into global scope 34 using std::move; 24 35 25 36 /// partner to move that copies any copyable type 26 37 template<typename T> 27 38 T copy( const T & x ) { return x; } 39 40 template< typename T > 41 static inline T * maybeClone( const T *orig ) { 42 if ( orig ) { 43 return orig->clone(); 44 } else { 45 return 0; 46 } // if 47 } 48 49 template< typename Input_iterator > 50 void printEnums( Input_iterator begin, Input_iterator end, const char * const *name_array, std::ostream &os ) { 51 for ( Input_iterator i = begin; i != end; ++i ) { 52 os << name_array[ *i ] << ' '; 53 } // for 54 } 55 56 template< typename Container > 57 void deleteAll( const Container &container ) { 58 for ( const auto &i : container ) { 59 delete i; 60 } // for 61 } 62 63 template< typename Container > 64 void printAll( const Container &container, std::ostream &os, Indenter indent = {} ) { 65 for ( typename Container::const_iterator i = container.begin(); i != container.end(); ++i ) { 66 if ( *i ) { 67 os << indent; 68 (*i)->print( os, indent ); 69 // need an endl after each element because it's not easy to know when each individual item should end 70 os << std::endl; 71 } // if 72 } // for 73 } 74 75 template< typename SrcContainer, typename DestContainer > 76 void cloneAll( const SrcContainer &src, DestContainer &dest ) { 77 typename SrcContainer::const_iterator in = src.begin(); 78 std::back_insert_iterator< DestContainer > out( dest ); 79 while ( in != src.end() ) { 80 *out++ = (*in++)->clone(); 81 } // while 82 } 83 84 template< typename SrcContainer, typename DestContainer, typename Predicate > 85 void cloneAll_if( const SrcContainer &src, DestContainer &dest, Predicate pred ) { 86 std::back_insert_iterator< DestContainer > out( dest ); 87 for ( auto x : src ) { 88 if ( pred(x) ) { 89 *out++ = x->clone(); 90 } 91 } // while 92 } 93 94 template< typename Container > 95 void assertAll( const Container &container ) { 96 int count = 0; 97 for ( typename Container::const_iterator i = container.begin(); i != container.end(); ++i ) { 98 if ( !(*i) ) { 99 std::cerr << count << " is null" << std::endl; 100 } // if 101 } // for 102 } 103 104 template < typename T > 105 std::list<T> tail( std::list<T> l ) { 106 if ( ! l.empty() ) { 107 std::list<T> ret(++(l.begin()), l.end()); 108 return ret; 109 } // if 110 } 111 112 template < typename T > 113 std::list<T> flatten( std::list < std::list<T> > l) { 114 typedef std::list <T> Ts; 115 116 Ts ret; 117 118 switch ( l.size() ) { 119 case 0: 120 return ret; 121 case 1: 122 return l.front(); 123 default: 124 ret = flatten(tail(l)); 125 ret.insert(ret.begin(), l.front().begin(), l.front().end()); 126 return ret; 127 } // switch 128 } 28 129 29 130 /// Splice src onto the end of dst, clearing src … … 42 143 } 43 144 44 /// Remove elements that match pred from the container. 145 template< typename... Args > 146 auto filter(Args&&... args) -> decltype(std::copy_if(std::forward<Args>(args)...)) { 147 return std::copy_if(std::forward<Args>(args)...); 148 } 149 150 template <typename E, typename UnaryPredicate, template< typename, typename...> class Container, typename... Args > 151 void filter( Container< E *, Args... > & container, UnaryPredicate pred, bool doDelete ) { 152 auto i = begin( container ); 153 while ( i != end( container ) ) { 154 auto it = next( i ); 155 if ( pred( *i ) ) { 156 if ( doDelete ) { 157 delete *i; 158 } // if 159 container.erase( i ); 160 } // if 161 i = it; 162 } // while 163 } 164 45 165 template<typename Container, typename Pred> 46 166 void erase_if( Container & cont, Pred && pred ) { -
src/InitTweak/FixInit.cpp
rf988834 r59c8dff 581 581 } 582 582 583 if ( nullptr == dtor->env && nullptr != env ) { 584 dtor->env = ast::shallowCopy( env ); 585 } 583 if ( ! dtor->env ) dtor->env = maybeClone( env ); 586 584 auto dtorFunc = getDtorFunc( ret, new ast::ExprStmt(loc, dtor ), stmtsToAddBefore ); 587 585 -
src/Parser/DeclarationNode.cc
rf988834 r59c8dff 35 35 #include "Common/SemanticError.h" // for SemanticError 36 36 #include "Common/UniqueName.h" // for UniqueName 37 #include "Common/utility.h" // for copy, spliceBegin37 #include "Common/utility.h" // for maybeClone 38 38 #include "Parser/ExpressionNode.h" // for ExpressionNode 39 39 #include "Parser/InitializerNode.h"// for InitializerNode … … 41 41 #include "TypeData.h" // for TypeData, TypeData::Aggregate_t 42 42 #include "TypedefTable.h" // for TypedefTable 43 44 class Initializer; 43 45 44 46 extern TypedefTable typedefTable; … … 99 101 DeclarationNode * DeclarationNode::clone() const { 100 102 DeclarationNode * newnode = new DeclarationNode; 101 newnode->set_next( maybeC opy( get_next() ) );103 newnode->set_next( maybeClone( get_next() ) ); 102 104 newnode->name = name ? new string( *name ) : nullptr; 103 105 104 106 newnode->builtin = NoBuiltinType; 105 newnode->type = maybeC opy( type );107 newnode->type = maybeClone( type ); 106 108 newnode->inLine = inLine; 107 109 newnode->storageClasses = storageClasses; 108 110 newnode->funcSpecs = funcSpecs; 109 newnode->bitfieldWidth = maybeC opy( bitfieldWidth );110 newnode->enumeratorValue.reset( maybeC opy( enumeratorValue.get() ) );111 newnode->bitfieldWidth = maybeClone( bitfieldWidth ); 112 newnode->enumeratorValue.reset( maybeClone( enumeratorValue.get() ) ); 111 113 newnode->hasEllipsis = hasEllipsis; 112 114 newnode->linkage = linkage; 113 115 newnode->asmName = maybeCopy( asmName ); 114 116 newnode->attributes = attributes; 115 newnode->initializer = maybeC opy( initializer );117 newnode->initializer = maybeClone( initializer ); 116 118 newnode->extension = extension; 117 newnode->asmStmt = maybeC opy( asmStmt );119 newnode->asmStmt = maybeClone( asmStmt ); 118 120 newnode->error = error; 119 121 120 122 // newnode->variable.name = variable.name ? new string( *variable.name ) : nullptr; 121 123 newnode->variable.tyClass = variable.tyClass; 122 newnode->variable.assertions = maybeC opy( variable.assertions );123 newnode->variable.initializer = maybeC opy( variable.initializer );124 125 newnode->assert.condition = maybeC opy( assert.condition );124 newnode->variable.assertions = maybeClone( variable.assertions ); 125 newnode->variable.initializer = maybeClone( variable.initializer ); 126 127 newnode->assert.condition = maybeClone( assert.condition ); 126 128 newnode->assert.message = maybeCopy( assert.message ); 127 129 return newnode; … … 662 664 dst->base->aggInst.aggregate = src; 663 665 if ( src->kind == TypeData::Aggregate ) { 664 dst->base->aggInst.params = maybeC opy( src->aggregate.actuals );666 dst->base->aggInst.params = maybeClone( src->aggregate.actuals ); 665 667 } // if 666 668 dst->base->qualifiers |= src->qualifiers; … … 692 694 if ( o->type->kind == TypeData::Aggregate ) { 693 695 type->aggInst.hoistType = o->type->aggregate.body; 694 type->aggInst.params = maybeC opy( o->type->aggregate.actuals );696 type->aggInst.params = maybeClone( o->type->aggregate.actuals ); 695 697 } else { 696 698 type->aggInst.hoistType = o->type->enumeration.body; … … 858 860 p->type->base->aggInst.aggregate = type; 859 861 if ( type->kind == TypeData::Aggregate ) { 860 p->type->base->aggInst.params = maybeC opy( type->aggregate.actuals );862 p->type->base->aggInst.params = maybeClone( type->aggregate.actuals ); 861 863 } // if 862 864 p->type->base->qualifiers |= type->qualifiers; … … 895 897 lastArray->base->aggInst.aggregate = type; 896 898 if ( type->kind == TypeData::Aggregate ) { 897 lastArray->base->aggInst.params = maybeC opy( type->aggregate.actuals );899 lastArray->base->aggInst.params = maybeClone( type->aggregate.actuals ); 898 900 } // if 899 901 lastArray->base->qualifiers |= type->qualifiers; … … 948 950 DeclarationNode * DeclarationNode::cloneType( string * name ) { 949 951 DeclarationNode * newnode = newName( name ); 950 newnode->type = maybeC opy( type );952 newnode->type = maybeClone( type ); 951 953 newnode->copySpecifiers( this ); 952 954 return newnode; … … 982 984 } // if 983 985 984 newType->forall = maybeC opy( type->forall );986 newType->forall = maybeClone( type->forall ); 985 987 if ( ! o->type ) { 986 988 o->type = newType; -
src/Parser/ParseNode.h
rf988834 r59c8dff 30 30 #include "Common/SemanticError.h" // for SemanticError 31 31 #include "Common/UniqueName.h" // for UniqueName 32 #include "Common/utility.h" // for maybeClone 32 33 #include "Parser/parserutility.h" // for maybeBuild, maybeCopy 33 34 -
src/Parser/TypeData.cc
rf988834 r59c8dff 167 167 TypeData * newtype = new TypeData( kind ); 168 168 newtype->qualifiers = qualifiers; 169 newtype->base = maybeC opy( base );170 newtype->forall = maybeC opy( forall );169 newtype->base = maybeClone( base ); 170 newtype->forall = maybeClone( forall ); 171 171 172 172 switch ( kind ) { … … 185 185 break; 186 186 case Array: 187 newtype->array.dimension = maybeC opy( array.dimension );187 newtype->array.dimension = maybeClone( array.dimension ); 188 188 newtype->array.isVarLen = array.isVarLen; 189 189 newtype->array.isStatic = array.isStatic; 190 190 break; 191 191 case Function: 192 newtype->function.params = maybeC opy( function.params );193 newtype->function.idList = maybeC opy( function.idList );194 newtype->function.oldDeclList = maybeC opy( function.oldDeclList );195 newtype->function.body = maybeC opy( function.body );196 newtype->function.withExprs = maybeC opy( function.withExprs );192 newtype->function.params = maybeClone( function.params ); 193 newtype->function.idList = maybeClone( function.idList ); 194 newtype->function.oldDeclList = maybeClone( function.oldDeclList ); 195 newtype->function.body = maybeClone( function.body ); 196 newtype->function.withExprs = maybeClone( function.withExprs ); 197 197 break; 198 198 case Aggregate: 199 199 newtype->aggregate.kind = aggregate.kind; 200 200 newtype->aggregate.name = aggregate.name ? new string( *aggregate.name ) : nullptr; 201 newtype->aggregate.params = maybeC opy( aggregate.params );202 newtype->aggregate.actuals = maybeC opy( aggregate.actuals );203 newtype->aggregate.fields = maybeC opy( aggregate.fields );201 newtype->aggregate.params = maybeClone( aggregate.params ); 202 newtype->aggregate.actuals = maybeClone( aggregate.actuals ); 203 newtype->aggregate.fields = maybeClone( aggregate.fields ); 204 204 newtype->aggregate.body = aggregate.body; 205 205 newtype->aggregate.anon = aggregate.anon; … … 208 208 break; 209 209 case AggregateInst: 210 newtype->aggInst.aggregate = maybeC opy( aggInst.aggregate );211 newtype->aggInst.params = maybeC opy( aggInst.params );210 newtype->aggInst.aggregate = maybeClone( aggInst.aggregate ); 211 newtype->aggInst.params = maybeClone( aggInst.params ); 212 212 newtype->aggInst.hoistType = aggInst.hoistType; 213 213 break; 214 214 case Enum: 215 215 newtype->enumeration.name = enumeration.name ? new string( *enumeration.name ) : nullptr; 216 newtype->enumeration.constants = maybeC opy( enumeration.constants );216 newtype->enumeration.constants = maybeClone( enumeration.constants ); 217 217 newtype->enumeration.body = enumeration.body; 218 218 newtype->enumeration.anon = enumeration.anon; … … 221 221 case SymbolicInst: 222 222 newtype->symbolic.name = symbolic.name ? new string( *symbolic.name ) : nullptr; 223 newtype->symbolic.params = maybeC opy( symbolic.params );224 newtype->symbolic.actuals = maybeC opy( symbolic.actuals );225 newtype->symbolic.assertions = maybeC opy( symbolic.assertions );223 newtype->symbolic.params = maybeClone( symbolic.params ); 224 newtype->symbolic.actuals = maybeClone( symbolic.actuals ); 225 newtype->symbolic.assertions = maybeClone( symbolic.assertions ); 226 226 newtype->symbolic.isTypedef = symbolic.isTypedef; 227 227 break; 228 228 case Tuple: 229 newtype->tuple = maybeC opy( tuple );229 newtype->tuple = maybeClone( tuple ); 230 230 break; 231 231 case Typeof: 232 232 case Basetypeof: 233 newtype->typeexpr = maybeC opy( typeexpr );233 newtype->typeexpr = maybeClone( typeexpr ); 234 234 break; 235 235 case Vtable: … … 240 240 break; 241 241 case Qualified: 242 newtype->qualified.parent = maybeC opy( qualified.parent );243 newtype->qualified.child = maybeC opy( qualified.child );242 newtype->qualified.parent = maybeClone( qualified.parent ); 243 newtype->qualified.child = maybeClone( qualified.child ); 244 244 break; 245 245 } // switch -
src/Parser/parser.yy
rf988834 r59c8dff 1960 1960 // Append the return type at the start (left-hand-side) to each identifier in the list. 1961 1961 DeclarationNode * ret = new DeclarationNode; 1962 ret->type = maybeC opy( $1->type->base );1962 ret->type = maybeClone( $1->type->base ); 1963 1963 $$ = $1->appendList( DeclarationNode::newFunction( $3, ret, $6, nullptr ) ); 1964 1964 } -
src/Parser/parserutility.h
rf988834 r59c8dff 36 36 37 37 template<typename node_t> 38 static inlinenode_t * maybeCopy( node_t const * node ) {38 node_t * maybeCopy( node_t const * node ) { 39 39 return node ? ast::shallowCopy( node ) : nullptr; 40 40 } -
src/SymTab/GenImplicitCall.cpp
rf988834 r59c8dff 25 25 #include "CodeGen/OperatorTable.h" // for isCtorDtor 26 26 #include "Common/UniqueName.h" // for UniqueName 27 #include "Common/utility.h" // for splice28 27 29 28 namespace SymTab { -
src/Validate/Autogen.cpp
rf988834 r59c8dff 445 445 446 446 auto * paramType = ast::deepCopy( member->get_type() ); 447 erase_if( paramType->attributes, []( ast::Attribute const * attr ){ 448 return !attr->isValidOnFuncParam(); 449 } ); 447 paramType->attributes.clear(); 450 448 ast::ObjectDecl * param = new ast::ObjectDecl( 451 449 getLocation(), member->name, paramType ); -
src/Validate/ReplaceTypedef.cpp
rf988834 r59c8dff 25 25 26 26 namespace { 27 28 bool isNonParameterAttribute( ast::Attribute const * attr ) { 29 static const std::vector<std::string> bad_names = { 30 "aligned", "__aligned__", 31 }; 32 for ( auto name : bad_names ) { 33 if ( name == attr->name ) { 34 return true; 35 } 36 } 37 return false; 38 } 27 39 28 40 struct ReplaceTypedefCore final : … … 89 101 // by typedef. GCC appears to do the same thing. 90 102 if ( isAtFunctionTop ) { 91 erase_if( ret->attributes, []( ast::Attribute const * attr ){ 92 return !attr->isValidOnFuncParam(); 93 } ); 103 erase_if( ret->attributes, isNonParameterAttribute ); 94 104 } 95 105 for ( const auto & attribute : type->attributes ) { -
tests/Makefile.am
rf988834 r59c8dff 92 92 concurrency/channels/parallel_harness.hfa \ 93 93 array-collections/dimexpr-match.hfa \ 94 array-collections/dimexpr-match-detail.sh \ 95 array-collections/array-raii.hfa 94 array-collections/dimexpr-match-detail.sh 96 95 97 96 dist-hook: -
tests/collections/.expect/string-api-coverage.txt
rf988834 r59c8dff 14 14 true false 15 15 true false 16 123456717 16 123 18 17 hello 19 hell20 18 hello 21 19 world 22 20 hello 23 21 world 24 Q25 123456726 hello27 Q28 12329 hell30 123456731 hello32 12333 hell34 22 5 35 23 helloworld … … 41 29 hello, friend 42 30 bye, friend 43 ohello44 ohell45 ohell46 omydarling47 omy48 omy49 hellohellohellohello50 31 hellohellohello 51 32 QQQ 52 33 asdfasdfasdf 53 lo54 hello heliocentric55 34 e 56 35 help!!!o -
tests/collections/.expect/string-compare.txt
rf988834 r59c8dff 1 1 ------- string ------- 2 ( strcmp(s_, s_) == 0) ok2 (cmp(s_, s_) == 0) ok 3 3 (s_ == s_) ok 4 4 !(s_ != s_) ok … … 7 7 (s_ <= s_) ok 8 8 !(s_ < s_) ok 9 ( strcmp("", s_) == 0) ok9 (cmp("", s_) == 0) ok 10 10 ("" == s_) ok 11 11 !("" != s_) ok … … 14 14 ("" <= s_) ok 15 15 !("" < s_) ok 16 ( strcmp(s_, "") == 0) ok16 (cmp(s_, "") == 0) ok 17 17 (s_ == "") ok 18 18 !(s_ != "") ok … … 21 21 (s_ <= "") ok 22 22 !(s_ < "") ok 23 ( strcmp(s_, s_a) < 0) ok23 (cmp(s_, s_a) < 0) ok 24 24 !(s_ == s_a) ok 25 25 (s_ != s_a) ok … … 28 28 (s_ <= s_a) ok 29 29 (s_ < s_a) ok 30 ( strcmp("", s_a) < 0) ok30 (cmp("", s_a) < 0) ok 31 31 !("" == s_a) ok 32 32 ("" != s_a) ok … … 35 35 ("" <= s_a) ok 36 36 ("" < s_a) ok 37 ( strcmp(s_, "a") < 0) ok37 (cmp(s_, "a") < 0) ok 38 38 !(s_ == "a") ok 39 39 (s_ != "a") ok … … 42 42 (s_ <= "a") ok 43 43 (s_ < "a") ok 44 ( strcmp(s_a, s_) > 0) ok44 (cmp(s_a, s_) > 0) ok 45 45 !(s_a == s_) ok 46 46 (s_a != s_) ok … … 49 49 !(s_a <= s_) ok 50 50 !(s_a < s_) ok 51 ( strcmp("a", s_) > 0) ok51 (cmp("a", s_) > 0) ok 52 52 !("a" == s_) ok 53 53 ("a" != s_) ok … … 56 56 !("a" <= s_) ok 57 57 !("a" < s_) ok 58 ( strcmp(s_a, "") > 0) ok58 (cmp(s_a, "") > 0) ok 59 59 !(s_a == "") ok 60 60 (s_a != "") ok … … 63 63 !(s_a <= "") ok 64 64 !(s_a < "") ok 65 ( strcmp(s_, s_aa) < 0) ok65 (cmp(s_, s_aa) < 0) ok 66 66 !(s_ == s_aa) ok 67 67 (s_ != s_aa) ok … … 70 70 (s_ <= s_aa) ok 71 71 (s_ < s_aa) ok 72 ( strcmp("", s_aa) < 0) ok72 (cmp("", s_aa) < 0) ok 73 73 !("" == s_aa) ok 74 74 ("" != s_aa) ok … … 77 77 ("" <= s_aa) ok 78 78 ("" < s_aa) ok 79 ( strcmp(s_, "aa") < 0) ok79 (cmp(s_, "aa") < 0) ok 80 80 !(s_ == "aa") ok 81 81 (s_ != "aa") ok … … 84 84 (s_ <= "aa") ok 85 85 (s_ < "aa") ok 86 ( strcmp(s_aa, s_) > 0) ok86 (cmp(s_aa, s_) > 0) ok 87 87 !(s_aa == s_) ok 88 88 (s_aa != s_) ok … … 91 91 !(s_aa <= s_) ok 92 92 !(s_aa < s_) ok 93 ( strcmp("aa", s_) > 0) ok93 (cmp("aa", s_) > 0) ok 94 94 !("aa" == s_) ok 95 95 ("aa" != s_) ok … … 98 98 !("aa" <= s_) ok 99 99 !("aa" < s_) ok 100 ( strcmp(s_aa, "") > 0) ok100 (cmp(s_aa, "") > 0) ok 101 101 !(s_aa == "") ok 102 102 (s_aa != "") ok … … 105 105 !(s_aa <= "") ok 106 106 !(s_aa < "") ok 107 ( strcmp(s_a, s_aa) < 0) ok107 (cmp(s_a, s_aa) < 0) ok 108 108 !(s_a == s_aa) ok 109 109 (s_a != s_aa) ok … … 112 112 (s_a <= s_aa) ok 113 113 (s_a < s_aa) ok 114 ( strcmp("a", s_aa) < 0) ok114 (cmp("a", s_aa) < 0) ok 115 115 !("a" == s_aa) ok 116 116 ("a" != s_aa) ok … … 119 119 ("a" <= s_aa) ok 120 120 ("a" < s_aa) ok 121 ( strcmp(s_a, "aa") < 0) ok121 (cmp(s_a, "aa") < 0) ok 122 122 !(s_a == "aa") ok 123 123 (s_a != "aa") ok … … 126 126 (s_a <= "aa") ok 127 127 (s_a < "aa") ok 128 ( strcmp(s_aa, s_a) > 0) ok128 (cmp(s_aa, s_a) > 0) ok 129 129 !(s_aa == s_a) ok 130 130 (s_aa != s_a) ok … … 133 133 !(s_aa <= s_a) ok 134 134 !(s_aa < s_a) ok 135 ( strcmp("aa", s_a) > 0) ok135 (cmp("aa", s_a) > 0) ok 136 136 !("aa" == s_a) ok 137 137 ("aa" != s_a) ok … … 140 140 !("aa" <= s_a) ok 141 141 !("aa" < s_a) ok 142 ( strcmp(s_aa, "a") > 0) ok142 (cmp(s_aa, "a") > 0) ok 143 143 !(s_aa == "a") ok 144 144 (s_aa != "a") ok … … 147 147 !(s_aa <= "a") ok 148 148 !(s_aa < "a") ok 149 ( strcmp(s_a, s_a) == 0) ok149 (cmp(s_a, s_a) == 0) ok 150 150 (s_a == s_a) ok 151 151 !(s_a != s_a) ok … … 154 154 (s_a <= s_a) ok 155 155 !(s_a < s_a) ok 156 ( strcmp("a", s_a) == 0) ok156 (cmp("a", s_a) == 0) ok 157 157 ("a" == s_a) ok 158 158 !("a" != s_a) ok … … 161 161 ("a" <= s_a) ok 162 162 !("a" < s_a) ok 163 ( strcmp(s_a, "a") == 0) ok163 (cmp(s_a, "a") == 0) ok 164 164 (s_a == "a") ok 165 165 !(s_a != "a") ok … … 168 168 (s_a <= "a") ok 169 169 !(s_a < "a") ok 170 ( strcmp(s_aa, s_aa) == 0) ok170 (cmp(s_aa, s_aa) == 0) ok 171 171 (s_aa == s_aa) ok 172 172 !(s_aa != s_aa) ok … … 175 175 (s_aa <= s_aa) ok 176 176 !(s_aa < s_aa) ok 177 ( strcmp("aa", s_aa) == 0) ok177 (cmp("aa", s_aa) == 0) ok 178 178 ("aa" == s_aa) ok 179 179 !("aa" != s_aa) ok … … 182 182 ("aa" <= s_aa) ok 183 183 !("aa" < s_aa) ok 184 ( strcmp(s_aa, "aa") == 0) ok184 (cmp(s_aa, "aa") == 0) ok 185 185 (s_aa == "aa") ok 186 186 !(s_aa != "aa") ok … … 189 189 (s_aa <= "aa") ok 190 190 !(s_aa < "aa") ok 191 ( strcmp(s_a, s_b) < 0) ok191 (cmp(s_a, s_b) < 0) ok 192 192 !(s_a == s_b) ok 193 193 (s_a != s_b) ok … … 196 196 (s_a <= s_b) ok 197 197 (s_a < s_b) ok 198 ( strcmp("a", s_b) < 0) ok198 (cmp("a", s_b) < 0) ok 199 199 !("a" == s_b) ok 200 200 ("a" != s_b) ok … … 203 203 ("a" <= s_b) ok 204 204 ("a" < s_b) ok 205 ( strcmp(s_a, "b") < 0) ok205 (cmp(s_a, "b") < 0) ok 206 206 !(s_a == "b") ok 207 207 (s_a != "b") ok … … 210 210 (s_a <= "b") ok 211 211 (s_a < "b") ok 212 ( strcmp(s_b, s_a) > 0) ok212 (cmp(s_b, s_a) > 0) ok 213 213 !(s_b == s_a) ok 214 214 (s_b != s_a) ok … … 217 217 !(s_b <= s_a) ok 218 218 !(s_b < s_a) ok 219 ( strcmp("b", s_a) > 0) ok219 (cmp("b", s_a) > 0) ok 220 220 !("b" == s_a) ok 221 221 ("b" != s_a) ok … … 224 224 !("b" <= s_a) ok 225 225 !("b" < s_a) ok 226 ( strcmp(s_b, "a") > 0) ok226 (cmp(s_b, "a") > 0) ok 227 227 !(s_b == "a") ok 228 228 (s_b != "a") ok … … 231 231 !(s_b <= "a") ok 232 232 !(s_b < "a") ok 233 ( strcmp(s_a, s_ba) < 0) ok233 (cmp(s_a, s_ba) < 0) ok 234 234 !(s_a == s_ba) ok 235 235 (s_a != s_ba) ok … … 238 238 (s_a <= s_ba) ok 239 239 (s_a < s_ba) ok 240 ( strcmp("a", s_ba) < 0) ok240 (cmp("a", s_ba) < 0) ok 241 241 !("a" == s_ba) ok 242 242 ("a" != s_ba) ok … … 245 245 ("a" <= s_ba) ok 246 246 ("a" < s_ba) ok 247 ( strcmp(s_a, "ba") < 0) ok247 (cmp(s_a, "ba") < 0) ok 248 248 !(s_a == "ba") ok 249 249 (s_a != "ba") ok … … 252 252 (s_a <= "ba") ok 253 253 (s_a < "ba") ok 254 ( strcmp(s_ba, s_a) > 0) ok254 (cmp(s_ba, s_a) > 0) ok 255 255 !(s_ba == s_a) ok 256 256 (s_ba != s_a) ok … … 259 259 !(s_ba <= s_a) ok 260 260 !(s_ba < s_a) ok 261 ( strcmp("ba", s_a) > 0) ok261 (cmp("ba", s_a) > 0) ok 262 262 !("ba" == s_a) ok 263 263 ("ba" != s_a) ok … … 266 266 !("ba" <= s_a) ok 267 267 !("ba" < s_a) ok 268 ( strcmp(s_ba, "a") > 0) ok268 (cmp(s_ba, "a") > 0) ok 269 269 !(s_ba == "a") ok 270 270 (s_ba != "a") ok … … 273 273 !(s_ba <= "a") ok 274 274 !(s_ba < "a") ok 275 ( strcmp(s_aa, s_ab) < 0) ok275 (cmp(s_aa, s_ab) < 0) ok 276 276 !(s_aa == s_ab) ok 277 277 (s_aa != s_ab) ok … … 280 280 (s_aa <= s_ab) ok 281 281 (s_aa < s_ab) ok 282 ( strcmp("aa", s_ab) < 0) ok282 (cmp("aa", s_ab) < 0) ok 283 283 !("aa" == s_ab) ok 284 284 ("aa" != s_ab) ok … … 287 287 ("aa" <= s_ab) ok 288 288 ("aa" < s_ab) ok 289 ( strcmp(s_aa, "ab") < 0) ok289 (cmp(s_aa, "ab") < 0) ok 290 290 !(s_aa == "ab") ok 291 291 (s_aa != "ab") ok … … 294 294 (s_aa <= "ab") ok 295 295 (s_aa < "ab") ok 296 ( strcmp(s_ab, s_aa) > 0) ok296 (cmp(s_ab, s_aa) > 0) ok 297 297 !(s_ab == s_aa) ok 298 298 (s_ab != s_aa) ok … … 301 301 !(s_ab <= s_aa) ok 302 302 !(s_ab < s_aa) ok 303 ( strcmp("ab", s_aa) > 0) ok303 (cmp("ab", s_aa) > 0) ok 304 304 !("ab" == s_aa) ok 305 305 ("ab" != s_aa) ok … … 308 308 !("ab" <= s_aa) ok 309 309 !("ab" < s_aa) ok 310 ( strcmp(s_ab, "aa") > 0) ok310 (cmp(s_ab, "aa") > 0) ok 311 311 !(s_ab == "aa") ok 312 312 (s_ab != "aa") ok … … 315 315 !(s_ab <= "aa") ok 316 316 !(s_ab < "aa") ok 317 ( strcmp(s_ba, s_bb) < 0) ok317 (cmp(s_ba, s_bb) < 0) ok 318 318 !(s_ba == s_bb) ok 319 319 (s_ba != s_bb) ok … … 322 322 (s_ba <= s_bb) ok 323 323 (s_ba < s_bb) ok 324 ( strcmp("ba", s_bb) < 0) ok324 (cmp("ba", s_bb) < 0) ok 325 325 !("ba" == s_bb) ok 326 326 ("ba" != s_bb) ok … … 329 329 ("ba" <= s_bb) ok 330 330 ("ba" < s_bb) ok 331 ( strcmp(s_ba, "bb") < 0) ok331 (cmp(s_ba, "bb") < 0) ok 332 332 !(s_ba == "bb") ok 333 333 (s_ba != "bb") ok … … 336 336 (s_ba <= "bb") ok 337 337 (s_ba < "bb") ok 338 ( strcmp(s_bb, s_ba) > 0) ok338 (cmp(s_bb, s_ba) > 0) ok 339 339 !(s_bb == s_ba) ok 340 340 (s_bb != s_ba) ok … … 343 343 !(s_bb <= s_ba) ok 344 344 !(s_bb < s_ba) ok 345 ( strcmp("bb", s_ba) > 0) ok345 (cmp("bb", s_ba) > 0) ok 346 346 !("bb" == s_ba) ok 347 347 ("bb" != s_ba) ok … … 350 350 !("bb" <= s_ba) ok 351 351 !("bb" < s_ba) ok 352 ( strcmp(s_bb, "ba") > 0) ok352 (cmp(s_bb, "ba") > 0) ok 353 353 !(s_bb == "ba") ok 354 354 (s_bb != "ba") ok … … 357 357 !(s_bb <= "ba") ok 358 358 !(s_bb < "ba") ok 359 ( strcmp(s_aa, s_b) < 0) ok359 (cmp(s_aa, s_b) < 0) ok 360 360 !(s_aa == s_b) ok 361 361 (s_aa != s_b) ok … … 364 364 (s_aa <= s_b) ok 365 365 (s_aa < s_b) ok 366 ( strcmp("aa", s_b) < 0) ok366 (cmp("aa", s_b) < 0) ok 367 367 !("aa" == s_b) ok 368 368 ("aa" != s_b) ok … … 371 371 ("aa" <= s_b) ok 372 372 ("aa" < s_b) ok 373 ( strcmp(s_aa, "b") < 0) ok373 (cmp(s_aa, "b") < 0) ok 374 374 !(s_aa == "b") ok 375 375 (s_aa != "b") ok … … 378 378 (s_aa <= "b") ok 379 379 (s_aa < "b") ok 380 ( strcmp(s_b, s_aa) > 0) ok380 (cmp(s_b, s_aa) > 0) ok 381 381 !(s_b == s_aa) ok 382 382 (s_b != s_aa) ok … … 385 385 !(s_b <= s_aa) ok 386 386 !(s_b < s_aa) ok 387 ( strcmp("b", s_aa) > 0) ok387 (cmp("b", s_aa) > 0) ok 388 388 !("b" == s_aa) ok 389 389 ("b" != s_aa) ok … … 392 392 !("b" <= s_aa) ok 393 393 !("b" < s_aa) ok 394 ( strcmp(s_b, "aa") > 0) ok394 (cmp(s_b, "aa") > 0) ok 395 395 !(s_b == "aa") ok 396 396 (s_b != "aa") ok … … 400 400 !(s_b < "aa") ok 401 401 ------- string_res ------- 402 ( strcmp(s_, s_) == 0) ok402 (cmp(s_, s_) == 0) ok 403 403 (s_ == s_) ok 404 404 !(s_ != s_) ok … … 407 407 (s_ <= s_) ok 408 408 !(s_ < s_) ok 409 ( strcmp("", s_) == 0) ok409 (cmp("", s_) == 0) ok 410 410 ("" == s_) ok 411 411 !("" != s_) ok … … 414 414 ("" <= s_) ok 415 415 !("" < s_) ok 416 ( strcmp(s_, "") == 0) ok416 (cmp(s_, "") == 0) ok 417 417 (s_ == "") ok 418 418 !(s_ != "") ok … … 421 421 (s_ <= "") ok 422 422 !(s_ < "") ok 423 ( strcmp(s_, s_a) < 0) ok423 (cmp(s_, s_a) < 0) ok 424 424 !(s_ == s_a) ok 425 425 (s_ != s_a) ok … … 428 428 (s_ <= s_a) ok 429 429 (s_ < s_a) ok 430 ( strcmp("", s_a) < 0) ok430 (cmp("", s_a) < 0) ok 431 431 !("" == s_a) ok 432 432 ("" != s_a) ok … … 435 435 ("" <= s_a) ok 436 436 ("" < s_a) ok 437 ( strcmp(s_, "a") < 0) ok437 (cmp(s_, "a") < 0) ok 438 438 !(s_ == "a") ok 439 439 (s_ != "a") ok … … 442 442 (s_ <= "a") ok 443 443 (s_ < "a") ok 444 ( strcmp(s_a, s_) > 0) ok444 (cmp(s_a, s_) > 0) ok 445 445 !(s_a == s_) ok 446 446 (s_a != s_) ok … … 449 449 !(s_a <= s_) ok 450 450 !(s_a < s_) ok 451 ( strcmp("a", s_) > 0) ok451 (cmp("a", s_) > 0) ok 452 452 !("a" == s_) ok 453 453 ("a" != s_) ok … … 456 456 !("a" <= s_) ok 457 457 !("a" < s_) ok 458 ( strcmp(s_a, "") > 0) ok458 (cmp(s_a, "") > 0) ok 459 459 !(s_a == "") ok 460 460 (s_a != "") ok … … 463 463 !(s_a <= "") ok 464 464 !(s_a < "") ok 465 ( strcmp(s_, s_aa) < 0) ok465 (cmp(s_, s_aa) < 0) ok 466 466 !(s_ == s_aa) ok 467 467 (s_ != s_aa) ok … … 470 470 (s_ <= s_aa) ok 471 471 (s_ < s_aa) ok 472 ( strcmp("", s_aa) < 0) ok472 (cmp("", s_aa) < 0) ok 473 473 !("" == s_aa) ok 474 474 ("" != s_aa) ok … … 477 477 ("" <= s_aa) ok 478 478 ("" < s_aa) ok 479 ( strcmp(s_, "aa") < 0) ok479 (cmp(s_, "aa") < 0) ok 480 480 !(s_ == "aa") ok 481 481 (s_ != "aa") ok … … 484 484 (s_ <= "aa") ok 485 485 (s_ < "aa") ok 486 ( strcmp(s_aa, s_) > 0) ok486 (cmp(s_aa, s_) > 0) ok 487 487 !(s_aa == s_) ok 488 488 (s_aa != s_) ok … … 491 491 !(s_aa <= s_) ok 492 492 !(s_aa < s_) ok 493 ( strcmp("aa", s_) > 0) ok493 (cmp("aa", s_) > 0) ok 494 494 !("aa" == s_) ok 495 495 ("aa" != s_) ok … … 498 498 !("aa" <= s_) ok 499 499 !("aa" < s_) ok 500 ( strcmp(s_aa, "") > 0) ok500 (cmp(s_aa, "") > 0) ok 501 501 !(s_aa == "") ok 502 502 (s_aa != "") ok … … 505 505 !(s_aa <= "") ok 506 506 !(s_aa < "") ok 507 ( strcmp(s_a, s_aa) < 0) ok507 (cmp(s_a, s_aa) < 0) ok 508 508 !(s_a == s_aa) ok 509 509 (s_a != s_aa) ok … … 512 512 (s_a <= s_aa) ok 513 513 (s_a < s_aa) ok 514 ( strcmp("a", s_aa) < 0) ok514 (cmp("a", s_aa) < 0) ok 515 515 !("a" == s_aa) ok 516 516 ("a" != s_aa) ok … … 519 519 ("a" <= s_aa) ok 520 520 ("a" < s_aa) ok 521 ( strcmp(s_a, "aa") < 0) ok521 (cmp(s_a, "aa") < 0) ok 522 522 !(s_a == "aa") ok 523 523 (s_a != "aa") ok … … 526 526 (s_a <= "aa") ok 527 527 (s_a < "aa") ok 528 ( strcmp(s_aa, s_a) > 0) ok528 (cmp(s_aa, s_a) > 0) ok 529 529 !(s_aa == s_a) ok 530 530 (s_aa != s_a) ok … … 533 533 !(s_aa <= s_a) ok 534 534 !(s_aa < s_a) ok 535 ( strcmp("aa", s_a) > 0) ok535 (cmp("aa", s_a) > 0) ok 536 536 !("aa" == s_a) ok 537 537 ("aa" != s_a) ok … … 540 540 !("aa" <= s_a) ok 541 541 !("aa" < s_a) ok 542 ( strcmp(s_aa, "a") > 0) ok542 (cmp(s_aa, "a") > 0) ok 543 543 !(s_aa == "a") ok 544 544 (s_aa != "a") ok … … 547 547 !(s_aa <= "a") ok 548 548 !(s_aa < "a") ok 549 ( strcmp(s_a, s_a) == 0) ok549 (cmp(s_a, s_a) == 0) ok 550 550 (s_a == s_a) ok 551 551 !(s_a != s_a) ok … … 554 554 (s_a <= s_a) ok 555 555 !(s_a < s_a) ok 556 ( strcmp("a", s_a) == 0) ok556 (cmp("a", s_a) == 0) ok 557 557 ("a" == s_a) ok 558 558 !("a" != s_a) ok … … 561 561 ("a" <= s_a) ok 562 562 !("a" < s_a) ok 563 ( strcmp(s_a, "a") == 0) ok563 (cmp(s_a, "a") == 0) ok 564 564 (s_a == "a") ok 565 565 !(s_a != "a") ok … … 568 568 (s_a <= "a") ok 569 569 !(s_a < "a") ok 570 ( strcmp(s_aa, s_aa) == 0) ok570 (cmp(s_aa, s_aa) == 0) ok 571 571 (s_aa == s_aa) ok 572 572 !(s_aa != s_aa) ok … … 575 575 (s_aa <= s_aa) ok 576 576 !(s_aa < s_aa) ok 577 ( strcmp("aa", s_aa) == 0) ok577 (cmp("aa", s_aa) == 0) ok 578 578 ("aa" == s_aa) ok 579 579 !("aa" != s_aa) ok … … 582 582 ("aa" <= s_aa) ok 583 583 !("aa" < s_aa) ok 584 ( strcmp(s_aa, "aa") == 0) ok584 (cmp(s_aa, "aa") == 0) ok 585 585 (s_aa == "aa") ok 586 586 !(s_aa != "aa") ok … … 589 589 (s_aa <= "aa") ok 590 590 !(s_aa < "aa") ok 591 ( strcmp(s_a, s_b) < 0) ok591 (cmp(s_a, s_b) < 0) ok 592 592 !(s_a == s_b) ok 593 593 (s_a != s_b) ok … … 596 596 (s_a <= s_b) ok 597 597 (s_a < s_b) ok 598 ( strcmp("a", s_b) < 0) ok598 (cmp("a", s_b) < 0) ok 599 599 !("a" == s_b) ok 600 600 ("a" != s_b) ok … … 603 603 ("a" <= s_b) ok 604 604 ("a" < s_b) ok 605 ( strcmp(s_a, "b") < 0) ok605 (cmp(s_a, "b") < 0) ok 606 606 !(s_a == "b") ok 607 607 (s_a != "b") ok … … 610 610 (s_a <= "b") ok 611 611 (s_a < "b") ok 612 ( strcmp(s_b, s_a) > 0) ok612 (cmp(s_b, s_a) > 0) ok 613 613 !(s_b == s_a) ok 614 614 (s_b != s_a) ok … … 617 617 !(s_b <= s_a) ok 618 618 !(s_b < s_a) ok 619 ( strcmp("b", s_a) > 0) ok619 (cmp("b", s_a) > 0) ok 620 620 !("b" == s_a) ok 621 621 ("b" != s_a) ok … … 624 624 !("b" <= s_a) ok 625 625 !("b" < s_a) ok 626 ( strcmp(s_b, "a") > 0) ok626 (cmp(s_b, "a") > 0) ok 627 627 !(s_b == "a") ok 628 628 (s_b != "a") ok … … 631 631 !(s_b <= "a") ok 632 632 !(s_b < "a") ok 633 ( strcmp(s_a, s_ba) < 0) ok633 (cmp(s_a, s_ba) < 0) ok 634 634 !(s_a == s_ba) ok 635 635 (s_a != s_ba) ok … … 638 638 (s_a <= s_ba) ok 639 639 (s_a < s_ba) ok 640 ( strcmp("a", s_ba) < 0) ok640 (cmp("a", s_ba) < 0) ok 641 641 !("a" == s_ba) ok 642 642 ("a" != s_ba) ok … … 645 645 ("a" <= s_ba) ok 646 646 ("a" < s_ba) ok 647 ( strcmp(s_a, "ba") < 0) ok647 (cmp(s_a, "ba") < 0) ok 648 648 !(s_a == "ba") ok 649 649 (s_a != "ba") ok … … 652 652 (s_a <= "ba") ok 653 653 (s_a < "ba") ok 654 ( strcmp(s_ba, s_a) > 0) ok654 (cmp(s_ba, s_a) > 0) ok 655 655 !(s_ba == s_a) ok 656 656 (s_ba != s_a) ok … … 659 659 !(s_ba <= s_a) ok 660 660 !(s_ba < s_a) ok 661 ( strcmp("ba", s_a) > 0) ok661 (cmp("ba", s_a) > 0) ok 662 662 !("ba" == s_a) ok 663 663 ("ba" != s_a) ok … … 666 666 !("ba" <= s_a) ok 667 667 !("ba" < s_a) ok 668 ( strcmp(s_ba, "a") > 0) ok668 (cmp(s_ba, "a") > 0) ok 669 669 !(s_ba == "a") ok 670 670 (s_ba != "a") ok … … 673 673 !(s_ba <= "a") ok 674 674 !(s_ba < "a") ok 675 ( strcmp(s_aa, s_ab) < 0) ok675 (cmp(s_aa, s_ab) < 0) ok 676 676 !(s_aa == s_ab) ok 677 677 (s_aa != s_ab) ok … … 680 680 (s_aa <= s_ab) ok 681 681 (s_aa < s_ab) ok 682 ( strcmp("aa", s_ab) < 0) ok682 (cmp("aa", s_ab) < 0) ok 683 683 !("aa" == s_ab) ok 684 684 ("aa" != s_ab) ok … … 687 687 ("aa" <= s_ab) ok 688 688 ("aa" < s_ab) ok 689 ( strcmp(s_aa, "ab") < 0) ok689 (cmp(s_aa, "ab") < 0) ok 690 690 !(s_aa == "ab") ok 691 691 (s_aa != "ab") ok … … 694 694 (s_aa <= "ab") ok 695 695 (s_aa < "ab") ok 696 ( strcmp(s_ab, s_aa) > 0) ok696 (cmp(s_ab, s_aa) > 0) ok 697 697 !(s_ab == s_aa) ok 698 698 (s_ab != s_aa) ok … … 701 701 !(s_ab <= s_aa) ok 702 702 !(s_ab < s_aa) ok 703 ( strcmp("ab", s_aa) > 0) ok703 (cmp("ab", s_aa) > 0) ok 704 704 !("ab" == s_aa) ok 705 705 ("ab" != s_aa) ok … … 708 708 !("ab" <= s_aa) ok 709 709 !("ab" < s_aa) ok 710 ( strcmp(s_ab, "aa") > 0) ok710 (cmp(s_ab, "aa") > 0) ok 711 711 !(s_ab == "aa") ok 712 712 (s_ab != "aa") ok … … 715 715 !(s_ab <= "aa") ok 716 716 !(s_ab < "aa") ok 717 ( strcmp(s_ba, s_bb) < 0) ok717 (cmp(s_ba, s_bb) < 0) ok 718 718 !(s_ba == s_bb) ok 719 719 (s_ba != s_bb) ok … … 722 722 (s_ba <= s_bb) ok 723 723 (s_ba < s_bb) ok 724 ( strcmp("ba", s_bb) < 0) ok724 (cmp("ba", s_bb) < 0) ok 725 725 !("ba" == s_bb) ok 726 726 ("ba" != s_bb) ok … … 729 729 ("ba" <= s_bb) ok 730 730 ("ba" < s_bb) ok 731 ( strcmp(s_ba, "bb") < 0) ok731 (cmp(s_ba, "bb") < 0) ok 732 732 !(s_ba == "bb") ok 733 733 (s_ba != "bb") ok … … 736 736 (s_ba <= "bb") ok 737 737 (s_ba < "bb") ok 738 ( strcmp(s_bb, s_ba) > 0) ok738 (cmp(s_bb, s_ba) > 0) ok 739 739 !(s_bb == s_ba) ok 740 740 (s_bb != s_ba) ok … … 743 743 !(s_bb <= s_ba) ok 744 744 !(s_bb < s_ba) ok 745 ( strcmp("bb", s_ba) > 0) ok745 (cmp("bb", s_ba) > 0) ok 746 746 !("bb" == s_ba) ok 747 747 ("bb" != s_ba) ok … … 750 750 !("bb" <= s_ba) ok 751 751 !("bb" < s_ba) ok 752 ( strcmp(s_bb, "ba") > 0) ok752 (cmp(s_bb, "ba") > 0) ok 753 753 !(s_bb == "ba") ok 754 754 (s_bb != "ba") ok … … 757 757 !(s_bb <= "ba") ok 758 758 !(s_bb < "ba") ok 759 ( strcmp(s_aa, s_b) < 0) ok759 (cmp(s_aa, s_b) < 0) ok 760 760 !(s_aa == s_b) ok 761 761 (s_aa != s_b) ok … … 764 764 (s_aa <= s_b) ok 765 765 (s_aa < s_b) ok 766 ( strcmp("aa", s_b) < 0) ok766 (cmp("aa", s_b) < 0) ok 767 767 !("aa" == s_b) ok 768 768 ("aa" != s_b) ok … … 771 771 ("aa" <= s_b) ok 772 772 ("aa" < s_b) ok 773 ( strcmp(s_aa, "b") < 0) ok773 (cmp(s_aa, "b") < 0) ok 774 774 !(s_aa == "b") ok 775 775 (s_aa != "b") ok … … 778 778 (s_aa <= "b") ok 779 779 (s_aa < "b") ok 780 ( strcmp(s_b, s_aa) > 0) ok780 (cmp(s_b, s_aa) > 0) ok 781 781 !(s_b == s_aa) ok 782 782 (s_b != s_aa) ok … … 785 785 !(s_b <= s_aa) ok 786 786 !(s_b < s_aa) ok 787 ( strcmp("b", s_aa) > 0) ok787 (cmp("b", s_aa) > 0) ok 788 788 !("b" == s_aa) ok 789 789 ("b" != s_aa) ok … … 792 792 !("b" <= s_aa) ok 793 793 !("b" < s_aa) ok 794 ( strcmp(s_b, "aa") > 0) ok794 (cmp(s_b, "aa") > 0) ok 795 795 !(s_b == "aa") ok 796 796 (s_b != "aa") ok -
tests/collections/.expect/string-istream-manip.txt
rf988834 r59c8dff 69 69 13 wwwwwwww 70 70 14 cccc 71 15 71 15 q 72 72 1 yyyyyyyyyyyyyyyyyyyy 73 73 2 abcxxx … … 84 84 13 wwwwwwww 85 85 14 cccc 86 15 86 15 q -
tests/collections/string-api-coverage.cfa
rf988834 r59c8dff 51 51 sout | (s == "hello") | (s == "world"); 52 52 sout | (s != "world") | (s != "hello"); 53 sout | ( frag == s(1, 3) ) | ( s3 == s(1,3) );54 sout | ( s3 != s(1, 3) ) | ( frag != s(1,3) );55 sout | ( s2(1, 3) == s(1,3) ) | ( s3(1,3) == s(1,3) );56 sout | ( s3(1, 3) != s(1,3) ) | ( s2(1,3) != s(1,3) );57 sout | ( s(1, 3) == frag ) | ( s(1,3) == s3 );58 sout | ( s(1, 3) != s3 ) | ( s(1,3) != frag );59 sout | ( s(1, 3) == "ell" ) | ( s(1,3) == "world" );60 sout | ( s(1, 3) != "world" ) | ( s(1,3) != "ell" );53 sout | ( frag == s(1,4) ) | ( s3 == s(1,4) ); 54 sout | ( s3 != s(1,4) ) | ( frag != s(1,4) ); 55 sout | ( s2(1,4) == s(1,4) ) | ( s3(1,4) == s(1,4) ); 56 sout | ( s3(1,4) != s(1,4) ) | ( s2(1,4) != s(1,4) ); 57 sout | ( s(1,4) == frag ) | ( s(1,4) == s3 ); 58 sout | ( s(1,4) != s3 ) | ( s(1,4) != frag ); 59 sout | ( s(1,4) == "ell" ) | ( s(1,4) == "world" ); 60 sout | ( s(1,4) != "world" ) | ( s(1,4) != "ell" ); 61 61 62 62 … … 66 66 // 67 67 { 68 string b1 = "1234567"; 69 sout | b1; // 1234567 70 71 string b1x = { "1234567", 3 }; 72 sout | b1x; // 123 68 string b1 = { "1234567", 3 }; 69 sout | b1; // 123 73 70 74 71 string b2 = s; 75 72 sout | b2; // hello 76 77 string b2x = { s, 4 };78 sout | b2x; // hell79 73 80 74 // todo: a plain string & … … 94 88 b4 = s_constref; 95 89 sout | b4; // world 96 97 string b5 = 'Q';98 sout | b5; // Q99 100 101 90 } 102 91 assertWellFormedHandleList( 10 ); 103 //104 // Assignments105 //106 {107 string b = "xxx";108 109 b = "1234567";110 sout | b; // 1234567111 112 b = "xxx";113 b = s;114 sout | b; // hello115 116 b = "xxx";117 b = 'Q';118 sout | b; // Q119 120 b = "xxx";121 assign( b, "1234567", 3 );122 sout | b; // 123123 124 b = "xxx";125 assign( b, s, 4 );126 sout | b; // hell127 128 b = "xxx";129 strcpy(b, "1234567");130 sout | b; // 1234567131 132 b = "xxx";133 strcpy(b, s);134 sout | b; // hello135 136 b = "xxx";137 strncpy( b, "1234567", 3 );138 sout | b; // 123139 140 b = "xxx";141 strncpy( b, s, 4 );142 sout | b; // hell143 }144 assertWellFormedHandleList( 10 );145 146 147 92 148 93 sout | size(s); // 5 … … 181 126 sout | sx; // bye, friend 182 127 183 sx = "o";184 strcat( sx, s );185 sout | sx; // ohello186 187 sx = "o";188 append( sx, s, 4 );189 sout | sx; // ohell190 191 sx = "o";192 strncat( sx, s, 4 );193 sout | sx; // ohell194 195 sx = "o";196 strcat( sx, "mydarling" );197 sout | sx; // omydarling198 199 sx = "o";200 append( sx, "mydarling", 2 );201 sout | sx; // omy202 203 sx = "o";204 strncat( sx, "mydarling", 2 );205 sout | sx; // omy206 207 128 // 208 129 // repetition 209 130 // 210 211 sx = s;212 sx *= 4;213 sout | sx; // hellohellohellohello214 215 131 sx = s * 3; 216 132 sout | sx; // hellohellohello … … 226 142 // 227 143 228 // Range cases treated thoroughly in "string-overwrite" test. 229 // Composability with comparison and search are demoed above and below. 230 // Coverage here adds the single-argument ("rest of string") overload. 231 232 sx = s; 233 sout | sx(3); // lo 234 sx(3) = "iocentric"; 235 sout | s | sx; // hello heliocentric 144 //... 236 145 237 146 // … … 335 244 | find( alphabet , "def") // 3 336 245 | find( alphabet( 0, 26), "def") // 3 337 | find( alphabet( 2, 2 4), "def") // 1338 | find( alphabet( 3, 2 3), "def") // 0339 | find( alphabet( 4, 2 2), "def") // 22, not found340 | find( alphabet( 4, 2 2), "ef") // 0246 | find( alphabet( 2, 26), "def") // 1 247 | find( alphabet( 3, 26), "def") // 0 248 | find( alphabet( 4, 26), "def") // 22, not found 249 | find( alphabet( 4, 26), "ef") // 0 341 250 | find( alphabet( 0, 6), "def") // 3 342 251 | find( alphabet( 0, 5), "def") // 5, not found … … 346 255 | includes( alphabet , "def") // true 347 256 | includes( alphabet( 0, 26), "def") // true 348 | includes( alphabet( 2, 2 4), "def") // true349 | includes( alphabet( 3, 2 3), "def") // true350 | includes( alphabet( 4, 2 2), "def") // false351 | includes( alphabet( 4, 2 2), "ef") // true257 | includes( alphabet( 2, 26), "def") // true 258 | includes( alphabet( 3, 26), "def") // true 259 | includes( alphabet( 4, 26), "def") // false 260 | includes( alphabet( 4, 26), "ef") // true 352 261 | includes( alphabet( 0, 6), "def") // true 353 262 | includes( alphabet( 0, 5), "def") // false … … 357 266 | startsWith( alphabet , "abc") // true 358 267 | startsWith( alphabet( 0, 26), "abc") // true 359 | startsWith( alphabet( 1, 2 5), "abc") // false360 | startsWith( alphabet( 1, 2 5), "bc") // true268 | startsWith( alphabet( 1, 26), "abc") // false 269 | startsWith( alphabet( 1, 26), "bc") // true 361 270 | startsWith( alphabet( 0, 26), "abc") // true 362 271 | startsWith( alphabet( 0, 4), "abc") // true … … 372 281 | endsWith( alphabet( 0, 25), "xy" ) // true 373 282 | endsWith( alphabet( 0, 26), "xyz") // true 374 | endsWith( alphabet(23, 3), "xyz") // true375 | endsWith( alphabet(24, 2), "xyz") // false376 | endsWith( alphabet(24, 2), "yz") // true283 | endsWith( alphabet(23, 26), "xyz") // true 284 | endsWith( alphabet(24, 26), "xyz") // false 285 | endsWith( alphabet(24, 26), "yz") // true 377 286 | endsWith( alphabet , "abc"); // false 378 287 -
tests/collections/string-compare.cfa
rf988834 r59c8dff 3 3 4 4 #define test_eq_(l, r) \ 5 chk( ( strcmp(l, r) == 0) ) \5 chk( (cmp(l, r) == 0) ) \ 6 6 chk( (l == r) ) \ 7 7 chk( !(l != r) ) \ … … 17 17 18 18 #define test_lt_(l, r) \ 19 chk( ( strcmp(l, r) < 0) ) \19 chk( (cmp(l, r) < 0) ) \ 20 20 chk( !(l == r) ) \ 21 21 chk( (l != r) ) \ … … 26 26 27 27 #define test_gt_(l, r) \ 28 chk( ( strcmp(l, r) > 0) ) \28 chk( (cmp(l, r) > 0) ) \ 29 29 chk( !(l == r) ) \ 30 30 chk( (l != r) ) \ -
tests/collections/string-overwrite.cfa
rf988834 r59c8dff 9 9 MS = modifier start 10 10 ME = modifier end 11 ML = modifier length12 11 WS = witness start 13 12 WE = witness end 14 WL = witness length15 13 16 14 The test does: … … 73 71 74 72 75 void showOneReplacement(string & s, int ms, int ml, int ws, int wl, const char* replaceWith) { 76 77 int me = ms + ml; 78 int we = ws + wl; 73 void showOneReplacement(string & s, int ms, int me, int ws, int we, const char* replaceWith) { 79 74 80 75 assert( ms >= 0 && ms <= me && me <= size(s) ); 81 76 assert( ws >= 0 && ws <= we && we <= size(s) ); 82 77 83 string mod = s(ms, m l)`shareEdits;84 string wit = s(ws, w l)`shareEdits;78 string mod = s(ms, me)`shareEdits; 79 string wit = s(ws, we)`shareEdits; 85 80 86 81 string modOld = mod; … … 123 118 void runReplaceCases() { 124 119 char * alphabetTemplate = "abcdefghijklmnopqrstuvwxyz"; 125 struct { int ms; int m l; int ws; int wl; char *replaceWith; char *label; } cases[] = {126 { 12, 2, 10, 10, "xxxxx", "warmup" },127 { 10, 0, 10,0, "=====", "1" },128 { 10, 0, 10,0, "==" , "" },129 { 10, 0, 10,0, "=" , "" },130 { 10, 0, 10,0, "" , "" },131 { 10, 2, 12, 0, "=====", "2" },132 { 10, 2, 12, 0, "==" , "" },133 { 10, 2, 12, 0, "=" , "" },134 { 10, 2, 12, 0, "" , "" },135 { 12, 0, 10,2, "=====", "3" },136 { 12, 0, 10,2, "==" , "" },137 { 12, 0, 10,2, "=" , "" },138 { 12, 0, 10,2, "" , "" },139 { 10, 0, 12, 0, "=====", "4" },140 { 10, 0, 12, 0, "==" , "" },141 { 10, 0, 12, 0, "=" , "" },142 { 10, 0, 12, 0, "" , "" },143 { 12, 0, 10,0, "=====", "5" },144 { 12, 0, 10,0, "==" , "" },145 { 12, 0, 10,0, "=" , "" },146 { 12, 0, 10,0, "" , "" },147 { 10, 2, 10,2, "=====", "6" },148 { 10, 2, 10,2, "==" , "" },149 { 10, 2, 10,2, "=" , "" },150 { 10, 2, 10,2, "" , "" },151 { 10, 2, 10,0, "=====", "7" },152 { 10, 2, 10,0, "==" , "" },153 { 10, 2, 10,0, "=" , "" },154 { 10, 2, 10,0, "" , "" },155 { 10, 0, 10,2, "=====", "8" },156 { 10, 0, 10,2, "==" , "" },157 { 10, 0, 10,2, "=" , "" },158 { 10, 0, 10,2, "" , "" },159 { 10, 2, 14, 0, "=====", "9" },160 { 10, 2, 14, 0, "==" , "" },161 { 10, 2, 14, 0, "=" , "" },162 { 10, 2, 14, 0, "" , "" },163 { 10, 4, 12, 2, "=====", "10" },164 { 10, 4, 12, 2, "==" , "" },165 { 10, 4, 12, 2, "=" , "" }, // FORMERLY unrunnable bug: tries to print seemingly infinite string166 { 10, 4, 12, 2, "" , "" }, // ditto167 { 14, 0, 10,2, "=====", "11" },168 { 14, 0, 10,2, "==" , "" },169 { 14, 0, 10,2, "=" , "" },170 { 14, 0, 10,2, "" , "" },171 { 12, 2, 10,4, "=====", "12" }, // correctness observation: watching klmn while mn |-> xxx gives klxxx because the mn is inside what I'm watching172 { 12, 2, 10,4, "==" , "" },173 { 12, 2, 10,4, "=" , "" },174 { 12, 2, 10,4, "" , "" },175 { 10, 2, 12, 2, "=====", "13" },176 { 10, 2, 12, 2, "==" , "" },177 { 10, 2, 12, 2, "=" , "" },178 { 10, 2, 12, 2, "" , "" },179 { 10, 4, 12, 0, "=====", "14" },180 { 10, 4, 12, 0, "==" , "" },181 { 10, 4, 12, 0, "=" , "" },182 { 10, 4, 12, 0, "" , "" },183 { 12, 2, 10,2, "=====", "15" },184 { 12, 2, 10,2, "==" , "" },185 { 12, 2, 10,2, "=" , "" },186 { 12, 2, 10,2, "" , "" },187 { 12, 0, 10,4, "=====", "16" },188 { 12, 0, 10,4, "==" , "" },189 { 12, 0, 10,4, "=" , "" },190 { 12, 0, 10,4, "" , "" },191 { 10, 4, 10,2, "=====", "17" },192 { 10, 4, 10,2, "==" , "" },193 { 10, 4, 10,2, "=" , "" },194 { 10, 4, 10,2, "" , "" },195 { 10, 0, 12, 2, "=====", "18" },196 { 10, 0, 12, 2, "==" , "" },197 { 10, 0, 12, 2, "=" , "" },198 { 10, 0, 12, 2, "" , "" },199 { 10, 2, 10,4, "=====", "19" },200 { 10, 2, 10,4, "==" , "" },201 { 10, 2, 10,4, "=" , "" },202 { 10, 2, 10,4, "" , "" },203 { 12, 2, 10,0, "=====", "20" },204 { 12, 2, 10,0, "==" , "" },205 { 12, 2, 10,0, "=" , "" },206 { 12, 2, 10,0, "" , "" },207 { 10, 2, 14, 2, "=====", "21" },208 { 10, 2, 14, 2, "==" , "" },209 { 10, 2, 14, 2, "=" , "" },210 { 10, 2, 14, 2, "" , "" },211 { 10, 4, 12, 4, "=====", "22" },212 { 10, 4, 12, 4, "==" , "" },213 { 10, 4, 12, 4, "=" , "" },214 { 10, 4, 12, 4, "" , "" },215 { 10, 6, 12, 2, "=====", "23" },216 { 10, 6, 12, 2, "==" , "" },217 { 10, 6, 12, 2, "=" , "" },218 { 10, 6, 12, 2, "" , "" },219 { 14, 2, 10,2, "=====", "24" },220 { 14, 2, 10,2, "==" , "" },221 { 14, 2, 10,2, "=" , "" },222 { 14, 2, 10,2, "" , "" },223 { 12, 4, 10,4, "=====", "25" },224 { 12, 4, 10,4, "==" , "" },225 { 12, 4, 10,4, "=" , "" },226 { 12, 4, 10,4, "" , "" },227 { 12, 2, 10,6, "=====", "26" },228 { 12, 2, 10,6, "==" , "" },229 { 12, 2, 10,6, "=" , "" },230 { 12, 2, 10,6, "" , "" },120 struct { int ms; int me; int ws; int we; char *replaceWith; char *label; } cases[] = { 121 { 12, 14, 10, 20, "xxxxx", "warmup" }, 122 { 10, 10, 10, 10, "=====", "1" }, 123 { 10, 10, 10, 10, "==" , "" }, 124 { 10, 10, 10, 10, "=" , "" }, 125 { 10, 10, 10, 10, "" , "" }, 126 { 10, 12, 12, 12, "=====", "2" }, 127 { 10, 12, 12, 12, "==" , "" }, 128 { 10, 12, 12, 12, "=" , "" }, 129 { 10, 12, 12, 12, "" , "" }, 130 { 12, 12, 10, 12, "=====", "3" }, 131 { 12, 12, 10, 12, "==" , "" }, 132 { 12, 12, 10, 12, "=" , "" }, 133 { 12, 12, 10, 12, "" , "" }, 134 { 10, 10, 12, 12, "=====", "4" }, 135 { 10, 10, 12, 12, "==" , "" }, 136 { 10, 10, 12, 12, "=" , "" }, 137 { 10, 10, 12, 12, "" , "" }, 138 { 12, 12, 10, 10, "=====", "5" }, 139 { 12, 12, 10, 10, "==" , "" }, 140 { 12, 12, 10, 10, "=" , "" }, 141 { 12, 12, 10, 10, "" , "" }, 142 { 10, 12, 10, 12, "=====", "6" }, 143 { 10, 12, 10, 12, "==" , "" }, 144 { 10, 12, 10, 12, "=" , "" }, 145 { 10, 12, 10, 12, "" , "" }, 146 { 10, 12, 10, 10, "=====", "7" }, 147 { 10, 12, 10, 10, "==" , "" }, 148 { 10, 12, 10, 10, "=" , "" }, 149 { 10, 12, 10, 10, "" , "" }, 150 { 10, 10, 10, 12, "=====", "8" }, 151 { 10, 10, 10, 12, "==" , "" }, 152 { 10, 10, 10, 12, "=" , "" }, 153 { 10, 10, 10, 12, "" , "" }, 154 { 10, 12, 14, 14, "=====", "9" }, 155 { 10, 12, 14, 14, "==" , "" }, 156 { 10, 12, 14, 14, "=" , "" }, 157 { 10, 12, 14, 14, "" , "" }, 158 { 10, 14, 12, 14, "=====", "10" }, 159 { 10, 14, 12, 14, "==" , "" }, 160 { 10, 14, 12, 14, "=" , "" }, // FORMERLY unrunnable bug: tries to print seemingly infinite string 161 { 10, 14, 12, 14, "" , "" }, // ditto 162 { 14, 14, 10, 12, "=====", "11" }, 163 { 14, 14, 10, 12, "==" , "" }, 164 { 14, 14, 10, 12, "=" , "" }, 165 { 14, 14, 10, 12, "" , "" }, 166 { 12, 14, 10, 14, "=====", "12" }, // correctness observation: watching klmn while mn |-> xxx gives klxxx because the mn is inside what I'm watching 167 { 12, 14, 10, 14, "==" , "" }, 168 { 12, 14, 10, 14, "=" , "" }, 169 { 12, 14, 10, 14, "" , "" }, 170 { 10, 12, 12, 14, "=====", "13" }, 171 { 10, 12, 12, 14, "==" , "" }, 172 { 10, 12, 12, 14, "=" , "" }, 173 { 10, 12, 12, 14, "" , "" }, 174 { 10, 14, 12, 12, "=====", "14" }, 175 { 10, 14, 12, 12, "==" , "" }, 176 { 10, 14, 12, 12, "=" , "" }, 177 { 10, 14, 12, 12, "" , "" }, 178 { 12, 14, 10, 12, "=====", "15" }, 179 { 12, 14, 10, 12, "==" , "" }, 180 { 12, 14, 10, 12, "=" , "" }, 181 { 12, 14, 10, 12, "" , "" }, 182 { 12, 12, 10, 14, "=====", "16" }, 183 { 12, 12, 10, 14, "==" , "" }, 184 { 12, 12, 10, 14, "=" , "" }, 185 { 12, 12, 10, 14, "" , "" }, 186 { 10, 14, 10, 12, "=====", "17" }, 187 { 10, 14, 10, 12, "==" , "" }, 188 { 10, 14, 10, 12, "=" , "" }, 189 { 10, 14, 10, 12, "" , "" }, 190 { 10, 10, 12, 14, "=====", "18" }, 191 { 10, 10, 12, 14, "==" , "" }, 192 { 10, 10, 12, 14, "=" , "" }, 193 { 10, 10, 12, 14, "" , "" }, 194 { 10, 12, 10, 14, "=====", "19" }, 195 { 10, 12, 10, 14, "==" , "" }, 196 { 10, 12, 10, 14, "=" , "" }, 197 { 10, 12, 10, 14, "" , "" }, 198 { 12, 14, 10, 10, "=====", "20" }, 199 { 12, 14, 10, 10, "==" , "" }, 200 { 12, 14, 10, 10, "=" , "" }, 201 { 12, 14, 10, 10, "" , "" }, 202 { 10, 12, 14, 16, "=====", "21" }, 203 { 10, 12, 14, 16, "==" , "" }, 204 { 10, 12, 14, 16, "=" , "" }, 205 { 10, 12, 14, 16, "" , "" }, 206 { 10, 14, 12, 16, "=====", "22" }, 207 { 10, 14, 12, 16, "==" , "" }, 208 { 10, 14, 12, 16, "=" , "" }, 209 { 10, 14, 12, 16, "" , "" }, 210 { 10, 16, 12, 14, "=====", "23" }, 211 { 10, 16, 12, 14, "==" , "" }, 212 { 10, 16, 12, 14, "=" , "" }, 213 { 10, 16, 12, 14, "" , "" }, 214 { 14, 16, 10, 12, "=====", "24" }, 215 { 14, 16, 10, 12, "==" , "" }, 216 { 14, 16, 10, 12, "=" , "" }, 217 { 14, 16, 10, 12, "" , "" }, 218 { 12, 16, 10, 14, "=====", "25" }, 219 { 12, 16, 10, 14, "==" , "" }, 220 { 12, 16, 10, 14, "=" , "" }, 221 { 12, 16, 10, 14, "" , "" }, 222 { 12, 14, 10, 16, "=====", "26" }, 223 { 12, 14, 10, 16, "==" , "" }, 224 { 12, 14, 10, 16, "=" , "" }, 225 { 12, 14, 10, 16, "" , "" }, 231 226 }; 232 227 for ( i; sizeof(cases)/sizeof(cases[0]) ) { 233 228 sout | "------------------------------------------------------------------------" | cases[i].label; 234 229 string replaceIn = alphabetTemplate; 235 showOneReplacement( replaceIn, cases[i].ms, cases[i].m l, cases[i].ws, cases[i].wl, cases[i].replaceWith );230 showOneReplacement( replaceIn, cases[i].ms, cases[i].me, cases[i].ws, cases[i].we, cases[i].replaceWith ); 236 231 } 237 232 } … … 249 244 string s = "abcdefghijklmnopqrstuvwxyz"; 250 245 251 s(5, 5) = "qqqqq"; // start=5, end=10, len=5252 253 sout | s; 254 255 256 s(5, 0) = "-----"; // start=5, end=5, len=0246 s(5,10) = "qqqqq"; // start=5, end=10, len=5 247 248 sout | s; 249 250 251 s(5,5) = "-----"; // start=5, end=5, len=0 257 252 258 253 sout | s; -
tests/concurrency/examples/quickSort.cfa
rf988834 r59c8dff 11 11 // Created On : Wed Dec 6 12:15:52 2017 12 12 // Last Modified By : Peter A. Buhr 13 // Last Modified On : Mon Jan 1 12:07:59 202414 // Update Count : 1 8813 // Last Modified On : Wed Feb 12 18:24:47 2020 14 // Update Count : 177 15 15 // 16 16 17 #include <fstream.hfa> // sin/sout 18 #include <stdlib.hfa> // convert 17 #include <fstream.hfa> 18 #include <stdlib.hfa> 19 #include <kernel.hfa> 19 20 #include <thread.hfa> 20 #include <math.hfa> // sqrt21 21 #include <string.h> // strcmp 22 22 … … 82 82 } // main 83 83 84 // convert(...) throws out_of_range or invalid_argument 85 ExceptionDecl( cmd_error ); 84 85 bool convert( int & val, const char * nptr ) { // convert C string to integer 86 char * eptr; 87 int temp = strto( nptr, &eptr, 10 ); // do not change val on false 88 // true => entire string valid with no extra characters 89 return *nptr != '\0' && *eptr == '\0' ? val = temp, true : false; 90 } // convert 91 92 void usage( char * argv[] ) { 93 sout | "Usage:" | argv[0] | "( -s unsorted-file [ sorted-file ] | -t size (>= 0) [ depth (>= 0) ] )"; 94 exit( EXIT_FAILURE ); // TERMINATE! 95 } // usage 96 86 97 87 98 int main( int argc, char * argv[] ) { 88 ifstream unsortedfile = sin; // default values 89 ofstream sortedfile = sout; 90 // Must be signed because of the conversion routine. 91 intmax_t depth = 0; 92 intmax_t size = -1; // -1 means time mode not activated 99 ifstream & unsortedfile = sin; 100 ofstream & sortedfile = sout; // default value 101 int depth = 0, size; 93 102 94 try { 95 if ( 1 < argc && strcmp( argv[1], "-t" ) == 0 ) { // time mode ? 103 if ( argc != 1 ) { // do not use defaults 104 if ( argc < 2 || argc > 4 ) usage( argv ); // wrong number of options 105 if ( strcmp( argv[1], "-t" ) == 0 ) { // timing ? 106 &unsortedfile = (ifstream *)0; // no input 96 107 choose ( argc ) { 97 108 case 4: 98 depth = convert( argv[3] ); // invalid integer ? 99 if ( depth < 0 ) throw ExceptionInst( cmd_error ); 109 if ( ! convert( depth, argv[3] ) || depth < 0 ) usage( argv ); 100 110 fallthrough; 101 111 case 3: 102 size = convert( argv[2] ); // invalid integer ? 103 if ( size < 0 ) throw ExceptionInst( cmd_error ); 104 default: // wrong number of options 105 throw ExceptionInst( cmd_error ); 112 if ( ! convert( size, argv[2] ) || size < 0 ) usage( argv ); 106 113 } // choose 107 114 } else { // sort file 108 115 choose ( argc ) { 109 case 4: 110 depth = convert( argv[3] ); // invalid integer ? 111 if ( depth < 0 ) throw ExceptionInst( cmd_error ); 112 fallthrough; 113 case 3: case 2: 114 if ( strcmp( argv[1], "d" ) != 0 ) { 115 try { // open input file first as output creates file 116 open( unsortedfile, argv[1] ); 117 } catch( open_failure * ) { // open failed ? 118 serr | "Error! Could not open unsorted input file \"" | argv[1] | "\""; 119 throw ExceptionInst( cmd_error ); 120 } // try 121 } // if 122 if ( argc > 2 && strcmp( argv[2], "d" ) != 0 ) { 123 try { 124 open( sortedfile, argv[2] ); 125 } catch( open_failure * ) { // open failed ? 126 serr | "Error! Could not open sorted output file \"" | argv[2] | "\""; 127 throw ExceptionInst( cmd_error ); 128 } // try 116 case 3: 117 &sortedfile = new( (const char *)argv[2] ); // open the output file 118 if ( fail( sortedfile ) ) { 119 serr | "Error! Could not open sorted output file \"" | argv[2] | "\""; 120 usage( argv ); 129 121 } // if 130 122 fallthrough; 131 case 1: ; // defaults 132 default: // wrong number of options 133 throw ExceptionInst( cmd_error ); 123 case 2: 124 &unsortedfile = new( (const char *)argv[1] ); // open the input file 125 if ( fail( unsortedfile ) ) { 126 serr | "Error! Could not open unsorted input file \"" | argv[1] | "\""; 127 usage( argv ); 128 } // if 134 129 } // choose 135 130 } // if 136 } catch( exception_t * ) { // catch any 137 exit | "Usage: " | argv[0] | // TERMINATE 138 " ( [ unsorted-file | 'd' [ sorted-file | 'd' [ depth (>= 0) ] ] ]" 139 " | -t size (>= 0) [ depth (>= 0) ] )"; 140 } // try 131 } // if 132 sortedfile | nlOff; // turn off auto newline 141 133 142 134 enum { ValuesPerLine = 22 }; // number of values printed per line 143 135 144 sortedfile | nlOff; // turn off auto newline 145 146 if ( size == -1 ) { // generate output ? 136 if ( &unsortedfile ) { // generate output ? 147 137 for () { 148 138 unsortedfile | size; // read number of elements in the list 149 139 if ( eof( unsortedfile ) ) break; 150 151 int * values = aalloc( size ); // values to be sorted, too large to put on stack 140 int * values = alloc( size ); // values to be sorted, too large to put on stack 152 141 for ( counter; size ) { // read unsorted numbers 153 142 unsortedfile | values[counter]; … … 157 146 } // for 158 147 sortedfile | nl; 159 160 148 if ( size > 0 ) { // values to sort ? 161 149 Quicksort QS = { values, size - 1, 0 }; // sort values … … 170 158 delete( values ); 171 159 } // for 172 } else { // timing 173 PRNG prng; 160 if ( &unsortedfile != &sin ) delete( &unsortedfile ); // close input/output files 161 if ( &sortedfile != &sout ) delete( &sortedfile ); 162 } else { 174 163 processor processors[ (1 << depth) - 1 ] __attribute__(( unused )); // create 2^depth-1 kernel threads 175 int * values = aalloc( size ); // values to be sorted, too large to put on stack176 164 165 int * values = alloc( size ); // values to be sorted, too large to put on stack 177 166 for ( counter; size ) { // generate unsorted numbers 178 167 values[counter] = size - counter; // descending values 179 168 } // for 180 181 unsigned int times = sqrt( size ); 182 for ( unsigned int counter = 0; counter < times; counter += 1 ) { 183 swap( values[0], values[prng(size)] ); // randomize unsorted numbers 169 for ( i; 200 ) { // random shuffle a few values 170 swap( values[rand() % size], values[rand() % size] ); 184 171 } // for 185 172 { -
tests/exceptions/hotpotato.cfa
rf988834 r59c8dff 5 5 6 6 struct Potato { 7 8 unsigned int deadline;// when timer goes off9 unsigned int timer;// up counter to deadline7 PRNG & prng; 8 unsigned int deadline; // when timer goes off 9 unsigned int timer; // up counter to deadline 10 10 }; // Potato 11 11 … … 16 16 &potato.prng = &prng; 17 17 reset( potato, maxTicks ); 18 18 } // Potato 19 19 20 20 coroutine Player { 21 22 int id;// player identity23 Potato & potato;// potato being tossed24 Player * partner[2];// left and right player21 PRNG & prng; 22 int id; // player identity 23 Potato & potato; // potato being tossed 24 Player * partner[2]; // left and right player 25 25 }; // Player 26 26 … … 29 29 player.id = id; 30 30 &player.potato = &potato; 31 31 } // Player 32 32 33 33 Player & umpire; … … 39 39 40 40 void reset( Potato & potato, unsigned int maxTicks ) with(potato) { 41 41 if ( maxTicks < 2 ) abort( "Hot Potato initialized with less than 2 ticks" ); // optional 42 42 deadline = prng( prng, 1, maxTicks ); 43 43 timer = 0; … … 60 60 enum { LEFT = 0, RIGHT = 1 }; 61 61 62 static void vote( Player & player, Election & election ) { 63 62 static void vote( Player & player, Election & election ) { // cause partner to vote 63 resumeAt( player, election ); 64 64 resume( player ); 65 65 } // vote … … 76 76 77 77 void main( Player & player ) with(player) { 78 suspend;// return immediately after establishing starter78 suspend; // return immediately after establishing starter 79 79 try { 80 81 poll();// check for non-local exceptions before proceeding82 83 84 85 86 87 88 countdown( potato );// player is eliminated if countdown() returned true89 90 91 92 resume( *partner[ side ] );// random toss left/right93 80 for ( ;; ) { 81 poll(); // check for non-local exceptions before proceeding 82 83 if ( partner[LEFT] == &player ) { // stop when only one player 84 sout | id | " wins the Match!"; 85 return; 86 } // exit 87 88 countdown( potato ); // player is eliminated if countdown() returned true 89 90 size_t side = prng( prng, 2 ); 91 sout | id | " -> " | nonl; 92 resume( *partner[ side ] ); // random toss left/right 93 } // for 94 94 } catchResume( Terminate * v ) { 95 95 v->victim->partner[LEFT]->partner[RIGHT] = v->victim->partner[RIGHT]; // unlink node 96 96 v->victim->partner[RIGHT]->partner[LEFT] = v->victim->partner[LEFT]; 97 97 delete( v->victim ); 98 98 reset( potato ); 99 99 sout | "U " | nonl; // start new game … … 102 102 sout | "election"; 103 103 sout | " -> " | id | nonl; 104 if ( id > getId( umpire ) ) &umpire = &player; 104 if ( id > getId( umpire ) ) &umpire = &player; // set umpire to highest id so far 105 105 vote( *partner[RIGHT], *election ); 106 106 } catchResume ( Explode * ) { 107 108 109 id = -1;// remove from election110 vote( *partner[RIGHT], ExceptionInst( Election ) );// start election111 112 113 114 115 resume( umpire );// resume umpire to terminate this player116 assert( false );// no return117 107 sout | id | " is eliminated"; 108 if ( &player == &umpire ) { 109 id = -1; // remove from election 110 vote( *partner[RIGHT], ExceptionInst( Election ) ); // start election 111 try { poll(); } catchResume( Election * election ) {} // handle end of election 112 sout | " : umpire " | getId( umpire ); 113 } // if 114 resumeAt( umpire, ExceptionInst( Terminate, &player ) ); 115 resume( umpire ); // resume umpire to terminate this player 116 assert( false ); // no return 117 } // try 118 118 } // main 119 119 … … 151 151 case 1: ; // defaults 152 152 default: // too many arguments 153 153 throw ExceptionInst( cmd_error ); 154 154 } // choose 155 155 } catch( exception_t * ) { // catch any 156 156 exit | "Usage: " | argv[0] 157 | " [ games (>=0) | 'd' (default " | DefaultGames158 | ") [ players (>=2) | 'd' (random " | MinNoPlayers | "-" | MaxNoPlayers159 | ") [ seed (>0) | 'd' (random) ] ] ]";157 | " [ games (>=0) | 'd' (default " | DefaultGames 158 | ") [ players (>=2) | 'd' (random " | MinNoPlayers | "-" | MaxNoPlayers 159 | ") [ seed (>0) | 'd' (random) ] ] ]"; 160 160 } // try 161 161 sout | numGames | numPlayers | seed; -
tests/exceptions/hotpotato_checked.cfa
rf988834 r59c8dff 5 5 6 6 struct Potato { 7 8 unsigned int deadline;// when timer goes off9 unsigned int timer;// up counter to deadline7 PRNG & prng; 8 unsigned int deadline; // when timer goes off 9 unsigned int timer; // up counter to deadline 10 10 }; // Potato 11 11 … … 16 16 &potato.prng = &prng; 17 17 reset( potato, maxTicks ); 18 18 } // Potato 19 19 20 20 coroutine Player { 21 22 int id;// player identity23 Potato & potato;// potato being tossed24 Player * partner[2];// left and right player21 PRNG & prng; 22 int id; // player identity 23 Potato & potato; // potato being tossed 24 Player * partner[2]; // left and right player 25 25 }; // Player 26 26 … … 29 29 player.id = id; 30 30 &player.potato = &potato; 31 31 } // Player 32 32 33 33 Player & umpire; … … 39 39 40 40 void reset( Potato & potato, unsigned int maxTicks ) with(potato) { 41 41 if ( maxTicks < 2 ) abort( "Hot Potato initialized with less than 2 ticks" ); // optional 42 42 deadline = prng( prng, 1, maxTicks ); 43 43 timer = 0; … … 66 66 static void terminate( Player & player ) { // resume umpire 67 67 resume( player ); 68 69 68 checked_poll(); 69 sout | "THIS SHOULD NOT BE REACHED"; 70 70 } // terminate 71 71 … … 74 74 partner[RIGHT] = &rp; 75 75 resume( player ); // establish main as starter for termination 76 76 checked_poll(); 77 77 } // init 78 78 … … 82 82 83 83 void toss( Player & player ) { // tossed the potato 84 84 resume( player ); 85 85 checked_poll(); 86 86 } // toss … … 88 88 void main( Player & player ) with(player) { 89 89 try { 90 enable_ehm();// allow delivery of nonlocal exceptions91 suspend;// return immediately after establishing starter92 93 94 95 96 97 98 99 100 101 countdown( potato );// player is eliminated if countdown() returned true102 103 104 105 toss( *partner[ side ] );// random toss left/right106 107 90 enable_ehm(); // allow delivery of nonlocal exceptions 91 suspend; // return immediately after establishing starter 92 checked_poll(); 93 94 for ( ;; ) { 95 checked_poll(); 96 if ( partner[LEFT] == &player ) { // stop when only one player 97 sout | id | " wins the Match!"; 98 return; 99 } // exit 100 101 countdown( potato ); // player is eliminated if countdown() returned true 102 103 size_t side = prng( prng, 2 ); 104 sout | id | " -> " | nonl; 105 toss( *partner[ side ] ); // random toss left/right 106 } // for 107 disable_ehm(); 108 108 } catchResume( Terminate * v ) { 109 109 v->victim->partner[LEFT]->partner[RIGHT] = v->victim->partner[RIGHT]; // unlink node 110 110 v->victim->partner[RIGHT]->partner[LEFT] = v->victim->partner[LEFT]; 111 111 delete( v->victim ); 112 112 reset( potato ); 113 113 sout | "U " | nonl; // start new game … … 116 116 sout | "election"; 117 117 sout | " -> " | id | nonl; 118 if ( id > getId( umpire ) ) &umpire = &player; 119 120 disable_ehm();// disable ehm since we can't handle execption thrown in vote here and want to poll later118 if ( id > getId( umpire ) ) &umpire = &player; // set umpire to highest id so far 119 resumeAt( *partner[RIGHT], *election ); 120 disable_ehm(); // disable ehm since we can't handle execption thrown in vote here and want to poll later 121 121 vote( *partner[RIGHT] ); 122 enable_ehm();// enable after vote122 enable_ehm(); // enable after vote 123 123 } catchResume( Explode * ) { 124 125 126 127 id = -1;// remove from election128 129 vote( *partner[RIGHT] );// start election130 131 132 133 134 135 136 137 assert( false );// no return138 124 sout | id | " is eliminated"; 125 if ( &player == &umpire ) { 126 try { 127 id = -1; // remove from election 128 resumeAt( *partner[RIGHT], ExceptionInst( Election ) ); 129 vote( *partner[RIGHT] ); // start election 130 checked_poll(); 131 } catchResume( Election * election ) { 132 sout | " : umpire " | getId( umpire ); 133 } // try 134 } // if 135 resumeAt( umpire, ExceptionInst( Terminate, &player ) ); 136 terminate( umpire ); 137 assert( false ); // no return 138 } // try 139 139 } // main 140 140 … … 172 172 case 1: ; // defaults 173 173 default: // too many arguments 174 174 throw ExceptionInst( cmd_error ); 175 175 } // choose 176 176 } catch( exception_t * ) { // catch any 177 177 exit | "Usage: " | argv[0] 178 | " [ games (>=0) | 'd' (default " | DefaultGames179 | ") [ players (>=2) | 'd' (random " | MinNoPlayers | "-" | MaxNoPlayers180 | ") [ seed (>0) | 'd' (random) ] ] ]";178 | " [ games (>=0) | 'd' (default " | DefaultGames 179 | ") [ players (>=2) | 'd' (random " | MinNoPlayers | "-" | MaxNoPlayers 180 | ") [ seed (>0) | 'd' (random) ] ] ]"; 181 181 } // try 182 182 sout | numGames | numPlayers | seed; -
tests/io/.expect/manipulatorsInput.arm64.txt
rf988834 r59c8dff 20 20 14 rc=1, cccc 21 21 15 rc=0, q 22 16 get this line23 17 @# this line 1)-{}24 18 abc25 19 abc26 20 d d27 28 d29 21 ZC44%30 22 1 yyyyyyyyyyyyyyyyyyyy 31 23 2 abcxxx … … 43 35 14 cccc 44 36 15 45 16 get this line46 17 @# this line 1)-{}47 18 abc48 19 abc49 20 d d50 51 d52 21 ZC44%53 37 a 54 38 a -
tests/io/.expect/manipulatorsInput.x64.txt
rf988834 r59c8dff 20 20 14 rc=1, cccc 21 21 15 rc=0, q 22 16 get this line23 17 @# this line 1)-{}24 18 abc25 19 abc26 20 d d27 28 d29 21 ZC44%30 22 1 yyyyyyyyyyyyyyyyyyyy 31 23 2 abcxxx … … 43 35 14 cccc 44 36 15 45 16 get this line46 17 @# this line 1)-{}47 18 abc48 19 abc49 20 d d50 51 d52 21 ZC44%53 37 a 54 38 a -
tests/io/.expect/manipulatorsInput.x86.txt
rf988834 r59c8dff 20 20 14 rc=1, cccc 21 21 15 rc=0, q 22 16 get this line23 17 @# this line 1)-{}24 18 abc25 19 abc26 20 d d27 28 d29 21 ZC44%30 22 1 yyyyyyyyyyyyyyyyyyyy 31 23 2 abcxxx … … 43 35 14 cccc 44 36 15 45 16 get this line46 17 @# this line 1)-{}47 18 abc48 19 abc49 20 d d50 51 d52 21 ZC44%53 37 a 54 38 a -
tests/io/.in/manipulatorsInput.txt
rf988834 r59c8dff 10 10 aaaaaaaaxxxxxxxxaabbccbbdddwwwbbbbbbbbwwwwwwwwaaaaaaaawwwwwwww 11 11 uuuuuccccuuuuu 12 get this line13 @# this line 1)-{}%14 "abc"15 'abc '16 { d d17 18 d }19 X ZC44%Y20 12 abc 21 13 cccccb … … 25 17 aaaaaaaaxxxxxxxxaabbccbbdddwwwbbbbbbbbwwwwwwwwaaaaaaaawwwwwwww 26 18 uuuuuccccuuuuu 27 get this line28 @# this line 1)-{}%29 "abc"30 'abc '31 { d d32 33 d }34 X ZC44%Y35 19 ab 36 20 0xff 017 15-15 -
tests/io/manipulatorsInput.cfa
rf988834 r59c8dff 7 7 // Created On : Sat Jun 8 17:58:54 2019 8 8 // Last Modified By : Peter A. Buhr 9 // Last Modified On : Wed Jan 3 11:15:04 202410 // Update Count : 1039 // Last Modified On : Sat Sep 2 14:27:46 2023 10 // Update Count : 65 11 11 // 12 12 … … 77 77 s[0] = 'q'; s[1] = '\0'; rc = 99; 78 78 rc = scanf( "%[^u]", s ); printf( "15 rc=%d, %s\n", rc, s ); 79 scanf( "%*[u]\n" ); 80 scanf( "%[^\n]\n", s ); printf( "16 %s\n", s ); 81 scanf( "%[^%%]%%\n", s ); printf( "17 %s\n", s ); 82 83 scanf( "%*[ \f\n\r\t\v]" ); // ignore whitespace 84 scanf( "\"%[^\"]\"", s ); printf( "18 %s\n", s ); 85 scanf( "%*[ \f\n\r\t\v]" ); // ignore whitespace 86 scanf( "'%[^']'", s ); printf( "19 %s\n", s ); 87 scanf( "%*[ \f\n\r\t\v]" ); // ignore whitespace 88 scanf( "{%[^}]}", s ); printf( "20 %s\n", s ); 89 scanf( "%*[ \f\n\r\t\v]" ); // ignore whitespace 90 scanf( "X%[^Y]Y", s ); printf( "21 %s\n", s ); 91 scanf( "\n" ); // must start next line 79 scanf( "%*[u]" ); 80 scanf("\n"); 92 81 } 93 82 { … … 113 102 s[0] = 'q'; s[1] = '\0'; 114 103 sin | excl( "u", wdi( sizeof(s), s ) ); sout | "15" | s; 115 sin | skip( "u" ) | "\n"; 116 sin | getline( wdi( sizeof(s), s ) ); sout | "16" | s; 117 sin | getline( wdi( sizeof(s), s ), '%' ) | "\n"; sout | "17" | s; 118 119 sin | quoted( wdi( sizeof(s), s ) ); sout | "18" | s; 120 sin | quoted( wdi( sizeof(s), s ), '\'' ); sout | "19" | s; 121 sin | quoted( wdi( sizeof(s), s ), '{', '}' ); sout | "20" | s; 122 sin | quoted( wdi( sizeof(s), s ), 'X', 'Y' ); sout | "21" | s; 123 } 124 // Keep harmonized with collections/string-istream-manip 104 sin | skip( "u" ); 105 sin | "\n"; 106 } 107 /* Keep harmonized with collections/string-istream-manip */ 125 108 { 126 109 char c;
Note:
See TracChangeset
for help on using the changeset viewer.