Changes in / [f988834:59c8dff]


Ignore:
Files:
6 deleted
42 edited

Legend:

Unmodified
Added
Removed
  • doc/LaTeXmacros/common.sty

    rf988834 r59c8dff  
    1111%% Created On       : Sat Apr  9 10:06:17 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Sun Jan 14 12:28:26 2024
    14 %% Update Count     : 631
     13%% Last Modified On : Fri Sep 29 16:48:59 2023
     14%% Update Count     : 587
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    273273\setlength{\columnposn}{\gcolumnposn}
    274274\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}}}}
    277276\newcommand{\CRT}{\global\columnposn=\gcolumnposn}
    278277
     
    293292xleftmargin=\parindentlnth,                             % indent code to paragraph indentation
    294293extendedchars=true,                                             % allow ASCII characters in the range 128-255
    295 escapechar=§,                                                   % LaTeX escape in CFA code §...§ (section symbol), emacs: C-q M-'
     294escapechar=\$,                                                  % LaTeX escape in CFA code §...§ (section symbol), emacs: C-q M-'
    296295mathescape=false,                                               % disable LaTeX math escape in CFA code $...$
    297296keepspaces=true,                                                %
     
    303302% replace/adjust listing characters that look bad in sanserif
    304303literate=
    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
    307305  {^}{\raisebox{0.6ex}{$\scriptstyle\land\,$}}1
    308306  {~}{\raisebox{0.3ex}{$\scriptstyle\sim\,$}}1
     
    310308  {<-}{$\leftarrow$}2
    311309  {=>}{$\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,
    313311}% lstset
    314312}% CFAStyle
  • doc/LaTeXmacros/common.tex

    rf988834 r59c8dff  
    1111%% Created On       : Sat Apr  9 10:06:17 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Sun Jan 14 17:59:02 2024
    14 %% Update Count     : 592
     13%% Last Modified On : Fri Sep 29 16:49:02 2023
     14%% Update Count     : 590
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    276276\setlength{\columnposn}{\gcolumnposn}
    277277\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}}}}
    280279\newcommand{\CRT}{\global\columnposn=\gcolumnposn}
    281280
     
    297296xleftmargin=\parindentlnth,                             % indent code to paragraph indentation
    298297extendedchars=true,                                             % allow ASCII characters in the range 128-255
    299 escapechar=§,                                                   % LaTeX escape in CFA code §...§ (section symbol), emacs: C-q M-'
     298escapechar=\$,                                                  % LaTeX escape in CFA code §...§ (section symbol), emacs: C-q M-'
    300299mathescape=false,                                               % disable LaTeX math escape in CFA code $...$
    301300keepspaces=true,                                                %
     
    307306% replace/adjust listing characters that look bad in sanserif
    308307literate=
    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
    311309  {^}{\raisebox{0.6ex}{$\scriptstyle\land\,$}}1
    312310  {~}{\raisebox{0.3ex}{$\scriptstyle\sim\,$}}1
     
    314312  {<-}{$\leftarrow$}2
    315313  {=>}{$\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,
    317315}% lstset
    318316}% CFAStyle
  • doc/user/user.tex

    rf988834 r59c8dff  
    1111%% Created On       : Wed Apr  6 14:53:29 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Sun Jan 14 17:27:41 2024
    14 %% Update Count     : 5764
     13%% Last Modified On : Sat Sep 30 22:46:19 2023
     14%% Update Count     : 5658
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    5555\SetWatermarkLightness{0.9}
    5656
    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}}}
    6061
    6162\setlength{\topmargin}{-0.45in}                                                 % move running title into header
     
    6667\CFAStyle                                                                                               % use default CFA format-style
    6768\setgcolumn{2.25in}
    68 \lstset{language=CFA}                                                                   % CFA default lnaguage
     69%\lstset{language=CFA}                                                                  % CFA default lnaguage
    6970\lstnewenvironment{C++}[1][]                            % use C++ style
    7071{\lstset{language=C++,moredelim=**[is][\protect\color{red}]{®}{®},#1}}
     
    171172\begin{tabular}{@{}lll@{}}
    172173\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}$
    175176
    176177int main( void ) {
     
    181182&
    182183\begin{cfa}[tabsize=3]
    183 #include <fstream>§\indexc{fstream}§
     184#include <fstream>$\indexc{fstream}$
    184185
    185186int main( void ) {
    186187        int x = 0, y = 1, z = 2;
    187         ®sout | x | y | z;®§\indexc{sout}§
     188        ®sout | x | y | z;®$\indexc{sout}$
    188189}
    189190\end{cfa}
    190191&
    191192\begin{cfa}[tabsize=3]
    192 #include <iostream>§\indexc{iostream}§
     193#include <iostream>$\indexc{iostream}$
    193194using namespace std;
    194195int main() {
     
    259260\begin{cfa}
    260261®forall( T )® T identity( T val ) { return val; }
    261 int forty_two = identity( 42 ); §\C{// T is bound to int, forty\_two == 42}§
     262int forty_two = identity( 42 ); $\C{// T is bound to int, forty\_two == 42}$
    262263\end{cfa}
    263264% extending the C type system with parametric polymorphism and overloading, as opposed to the \Index*[C++]{\CC{}} approach of object-oriented extensions.
     
    287288
    288289double 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}§
     290double * val = (double *)bsearch( &key, vals, 10, sizeof(vals[0]), comp ); $\C{// search sorted array}$
    290291\end{cfa}
    291292which can be augmented simply with a polymorphic, type-safe, \CFA-overloaded wrappers:
     
    296297
    297298forall( 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
     302double * val = bsearch( 5.0, vals, 10 ); $\C{// selection based on return type}$
    302303int posn = bsearch( 5.0, vals, 10 );
    303304\end{cfa}
     
    311312\begin{cfa}
    312313forall( 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}§
     314int * ip = malloc(); $\C{// select type and size from left-hand side}$
    314315double * dp = malloc();
    315316struct S {...} * sp = malloc();
     
    323324\begin{cfa}
    324325char ®abs®( char );
    325 extern "C" { int ®abs®( int ); } §\C{// use default C routine for int}§
     326extern "C" { int ®abs®( int ); } $\C{// use default C routine for int}$
    326327long int ®abs®( long int );
    327328long long int ®abs®( long long int );
     
    348349The command ©cfa© is used to compile a \CFA program and is based on the \Index{GNU} \Indexc{gcc} command, \eg:
    349350\begin{cfa}
    350 cfa§\indexc{cfa}\index{compilation!cfa@©cfa©}§ [ gcc/§\CFA{}§-options ] [ C/§\CFA{}§ source-files ] [ assembler/loader files ]
     351cfa$\indexc{cfa}\index{compilation!cfa@©cfa©}$ [ gcc/$\CFA{}$-options ] [ C/$\CFA{}$ source-files ] [ assembler/loader files ]
    351352\end{cfa}
    352353There 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.
     
    437438\begin{cfa}
    438439#ifndef __CFORALL__
    439 #include <stdio.h>§\indexc{stdio.h}§ §\C{// C header file}§
     440#include <stdio.h>$\indexc{stdio.h}$ $\C{// C header file}$
    440441#else
    441 #include <fstream>§\indexc{fstream}§ §\C{// \CFA header file}§
     442#include <fstream>$\indexc{fstream}$ $\C{// \CFA header file}$
    442443#endif
    443444\end{cfa}
     
    449450Each 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:
    450451\begin{lstlisting}[language=sh]
    451 cfa §test§.cfa -CFA -XCFA -p # print translated code without printing the standard prelude
    452 cfa §test§.cfa -XCFA -P -XCFA parse -XCFA -n # show program parse without prelude
     452cfa $test$.cfa -CFA -XCFA -p # print translated code without printing the standard prelude
     453cfa $test$.cfa -XCFA -P -XCFA parse -XCFA -n # show program parse without prelude
    453454\end{lstlisting}
    454 Alternatively, multiple flags can be specified separated with commas and \emph{without} spaces.
     455Alternatively, multiple flages can be specified separated with commas and \emph{without} spaces.
    455456\begin{lstlisting}[language=sh,{moredelim=**[is][\protect\color{red}]{®}{®}}]
    456 cfa §test§.cfa -XCFA®,®-Pparse®,®-n # show program parse without prelude
     457cfa $test$.cfa -XCFA®,®-Pparse®,®-n # show program parse without prelude
    457458\end{lstlisting}
    458459\begin{description}[topsep=5pt,itemsep=0pt,parsep=0pt]
     
    536537Keyword clashes are accommodated by syntactic transformations using the \CFA backquote escape-mechanism:
    537538\begin{cfa}
    538 int ®``®coroutine = 3;                                  §\C{// make keyword an identifier}§
     539int ®``®coroutine = 3;                                  $\C{// make keyword an identifier}$
    539540double ®``®forall = 3.5;
    540541\end{cfa}
     
    546547\begin{cfa}
    547548// 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}$
    550551#define __CFA_BFD_H__
    551552#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}$
    554555#undef with
    555556#undef __CFA_BFD_H__
     
    565566Numeric constants are extended to allow \Index{underscore}s\index{constant!underscore} as a separator, \eg:
    566567\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}§
     5682®_®147®_®483®_®648;                                    $\C{// decimal constant}$
     56956®_®ul;                                                                $\C{// decimal unsigned long constant}$
     5700®_®377;                                                                $\C{// octal constant}$
     5710x®_®ff®_®ff;                                                   $\C{// hexadecimal constant}$
     5720x®_®ef3d®_®aa5c;                                               $\C{// hexadecimal constant}$
     5733.141®_®592®_®654;                                              $\C{// floating constant}$
     57410®_®e®_®+1®_®00;                                               $\C{// floating constant}$
     5750x®_®ff®_®ff®_®p®_®3;                                   $\C{// hexadecimal floating}$
     5760x®_®1.ffff®_®ffff®_®p®_®128®_®l;               $\C{// hexadecimal floating long constant}$
     577L®_®$"\texttt{\textbackslash{x}}$®_®$\texttt{ff}$®_®$\texttt{ee}"$; $\C{// wide character constant}$
    577578\end{cfa}
    578579The rules for placement of underscores are:
     
    634635Declarations in the \Indexc{do}-©while© condition are not useful because they appear after the loop body.}
    635636\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}§
     637if ( ®int x = f()® ) ...                        $\C{// x != 0}$
     638if ( ®int x = f(), y = g()® ) ...       $\C{// x != 0 \&\& y != 0}$
     639if ( ®int x = f(), y = g(); x < y® ) ... $\C{// relational expression}$
     640if ( ®struct S { int i; } x = { f() }; x.i < 4® ) $\C{// relational expression}$
     641
     642while ( ®int x = f()® ) ...                     $\C{// x != 0}$
     643while ( ®int x = f(), y = g()® ) ... $\C{// x != 0 \&\& y != 0}$
     644while ( ®int x = f(), y = g(); x < y® ) ... $\C{// relational expression}$
     645while ( ®struct S { int i; } x = { f() }; x.i < 4® ) ... $\C{// relational expression}$
    645646\end{cfa}
    646647Unless 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.
     
    712713\begin{cfa}
    713714switch ( i ) {
    714   case 1§\R{\textvisiblespace}§®...®4:
     715  case 1$\R{\textvisiblespace}$®...®4:
    715716        ...
    716   case 10§\R{\textvisiblespace}§®...®13:
     717  case 10$\R{\textvisiblespace}$®...®13:
    717718        ...
    718719}
     
    751752  case 1:
    752753        ...
    753         §\R{\LstCommentStyle{// fall-through}}§
     754        $\R{\LstCommentStyle{// fall-through}}$
    754755  case 2:
    755756        ...
     
    852853\begin{cfa}
    853854switch ( 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}$
    856857  case 0: ...
    857858        ...
    858         ®int z = 0;® §\C{// unreachable initialization, cannot appear after case}§
     859        ®int z = 0;® $\C{// unreachable initialization, cannot appear after case}$
    859860        z = 2;
    860861  case 1:
    861         ®x = z;® §\C{// without fall through, z is uninitialized}§
     862        ®x = z;® $\C{// without fall through, z is uninitialized}$
    862863}
    863864\end{cfa}
     
    894895  case 1:  case 2:  case 3:
    895896        ...
    896         §\R{\LstCommentStyle{// implicit end of switch (break)}}§
     897        $\R{\LstCommentStyle{// implicit end of switch (break)}}$
    897898  case 5:
    898899        ...
    899         ®fallthru®; §\C{// explicit fall through}§
     900        ®fallthru®; $\C{// explicit fall through}$
    900901  case 7:
    901902        ...
    902         ®break® §\C{// explicit end of switch (redundant)}§
     903        ®break® $\C{// explicit end of switch (redundant)}$
    903904  default:
    904905        j = 3;
     
    921922\begin{cfa}
    922923switch ( x ) {
    923         ®int i = 0;®                                            §\C{// allowed only at start}§
     924        ®int i = 0;®                                            $\C{// allowed only at start}$
    924925  case 0:
    925926        ...
    926         ®int j = 0;®                                            §\C{// disallowed}§
     927        ®int j = 0;®                                            $\C{// disallowed}$
    927928  case 1:
    928929        {
    929                 ®int k = 0;®                                    §\C{// allowed at different nesting levels}§
     930                ®int k = 0;®                                    $\C{// allowed at different nesting levels}$
    930931                ...
    931           ®case 2:®                                                     §\C{// disallow case in nested statements}§
     932          ®case 2:®                                                     $\C{// disallow case in nested statements}$
    932933        }
    933934  ...
     
    10031004while () { sout | "empty"; break; }
    10041005do { 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;}§
     1006for () { sout | "empty"; break; }                                                       $\C[3in]{sout | nl | nlOff;}$
     1007
     1008for ( 0 ) { sout | "A"; } sout | "zero";                                        $\C{sout | nl;}$
     1009for ( 1 ) { sout | "A"; }                                                                       $\C{sout | nl;}$
     1010for ( 10 ) { sout | "A"; }                                                                      $\C{sout | nl;}$
     1011for ( ~= 10 ) { sout | "A"; }                                                           $\C{sout | nl;}$
     1012for ( 1 ~= 10 ~ 2 ) { sout | "B"; }                                                     $\C{sout | nl;}$
     1013for ( 1 -~= 10 ~ 2 ) { sout | "C"; }                                            $\C{sout | nl;}$
     1014for ( 0.5 ~ 5.5 ) { sout | "D"; }                                                       $\C{sout | nl;}$
     1015for ( 0.5 -~ 5.5 ) { sout | "E"; }                                                      $\C{sout | nl;}$
     1016for ( i; 10 ) { sout | i; }                                                                     $\C{sout | nl;}$
     1017for ( i; ~= 10 ) { sout | i; }                                                          $\C{sout | nl;}$
     1018for ( i; 1 ~= 10 ~ 2 ) { sout | i; }                                            $\C{sout | nl;}$
     1019for ( i; 1 -~= 10 ~ 2 ) { sout | i; }                                           $\C{sout | nl;}$
     1020for ( i; 0.5 ~ 5.5 ) { sout | i; }                                                      $\C{sout | nl;}$
     1021for ( i; 0.5 -~ 5.5 ) { sout | i; }                                                     $\C{sout | nl;}$
     1022for ( ui; 2u ~= 10u ~ 2u ) { sout | ui; }                                       $\C{sout | nl;}$
     1023for ( ui; 2u -~= 10u ~ 2u ) { sout | ui; }                                      $\C{sout | nl | nl | nl;}$
    10231024
    10241025enum { 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;}§
     1026for ( N ) { sout | "N"; }                                                                       $\C{sout | nl;}$
     1027for ( i; N ) { sout | i; }                                                                      $\C{sout | nl;}$
     1028for ( i; -~ N ) { sout | i; }                                                           $\C{sout | nl | nl | nl;}$
    10281029
    10291030const 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§
     1031for ( i; low ~ high ~ inc + 1 ) { sout | i; }                           $\C{sout | nl;}$
     1032for ( i; 1 ~ @ ) { if ( i > 10 ) break; sout | i; }                     $\C{sout | nl;}$
     1033for ( i; @ -~ 10 ) { if ( i < 0 ) break; sout | i; }            $\C{sout | nl;}$
     1034for ( i; 2 ~ @ ~ 2 ) { if ( i > 10 ) break; sout | i; }         $\C{sout | nl;}$
     1035for ( i; 2.1 ~ @ ~ @ ) { if ( i > 10.5 ) break; sout | i; i += 1.7; } $\C{sout | nl;}$
     1036for ( i; @ -~ 10 ~ 2 ) { if ( i < 0 ) break; sout | i; }        $\C{sout | nl;}$
     1037for ( i; 12.1 ~ @ ~ @ ) { if ( i < 2.5 ) break; sout | i; i -= 1.7; } $\C{sout | nl;}$
     1038for ( i; 5 : j; -5 ~ @ ) { sout | i | j; }                                      $\C{sout | nl;}$
     1039for ( i; 5 : j; @ -~ -5 ) { sout | i | j; }                                     $\C{sout | nl;}$
     1040for ( i; 5 : j; -5 ~ @ ~ 2 ) { sout | i | j; }                          $\C{sout | nl;}$
     1041for ( i; 5 : j; @ -~ -5 ~ 2 ) { sout | i | j; }                         $\C{sout | nl;}$
     1042for ( i; 5 : j; -5 ~ @ ) { sout | i | j; }                                      $\C{sout | nl;}$
     1043for ( i; 5 : j; @ -~ -5 ) { sout | i | j; }                                     $\C{sout | nl;}$
     1044for ( i; 5 : j; -5 ~ @ ~ 2 ) { sout | i | j; }                          $\C{sout | nl;}$
     1045for ( i; 5 : j; @ -~ -5 ~ 2 ) { sout | i | j; }                         $\C{sout | nl;}$
     1046for ( i; 5 : j; @ -~ -5 ~ 2 : k; 1.5 ~ @ ) { sout | i | j | k; } $\C{sout | nl;}$
     1047for ( i; 5 : j; @ -~ -5 ~ 2 : k; 1.5 ~ @ ) { sout | i | j | k; } $\C{sout | nl;}$
     1048for ( i; 5 : k; 1.5 ~ @ : j; @ -~ -5 ~ 2 ) { sout | i | j | k; } $\C{sout | nl;}\CRT$
    10481049\end{cfa}
    10491050&
     
    11161117The \Indexc{for}, \Indexc{while}, and \Indexc{do} loop-control allow an empty conditional, which implies a comparison value of ©1© (true).
    11171118\begin{cfa}
    1118 while ( ®/* empty */®  )                                §\C{// while ( true )}§
    1119 for ( ®/* empty */®  )                                  §\C{// for ( ; true; )}§
    1120 do ... while ( ®/* empty */®  )                 §\C{// do ... while ( true )}§
     1119while ( ®/* empty */®  )                                $\C{// while ( true )}$
     1120for ( ®/* empty */®  )                                  $\C{// for ( ; true; )}$
     1121do ... while ( ®/* empty */®  )                 $\C{// do ... while ( true )}$
    11211122\end{cfa}
    11221123
     
    11481149If 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.
    11491150\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}§
     1151for ( ®5® )                                                             $\C{// typeof(5) anonymous-index; 5 is high value}$
     1152for ( i; ®1.5® ~ 5.5 )                                  $\C{// typeof(1.5) i; 1.5 is low value}$
     1153for ( ®int i®; 0 ~ 10 ~ 2 )                             $\C{// int i; type is explicit}$
    11531154\end{cfa}
    11541155
     
    11581159H is implicit up-to exclusive range [0,H\R{)}.
    11591160\begin{cfa}
    1160 for ( ®5® )                                                             §\C{// for ( typeof(5) i; i < 5; i += 1 )}§
     1161for ( ®5® )                                                             $\C{// for ( typeof(5) i; i < 5; i += 1 )}$
    11611162\end{cfa}
    11621163\item
    11631164©~=© H is implicit up-to inclusive range [0,H\R{]}.
    11641165\begin{cfa}
    1165 for ( ®~=® 5 )                                                  §\C{// for ( typeof(5) i; i <= 5; i += 1 )}§
     1166for ( ®~=® 5 )                                                  $\C{// for ( typeof(5) i; i <= 5; i += 1 )}$
    11661167\end{cfa}
    11671168\item
    11681169L ©~©\index{~@©~©} H is explicit up-to exclusive range [L,H\R{)}.
    11691170\begin{cfa}
    1170 for ( 1 ®~® 5 )                                                 §\C{// for ( typeof(1) i = 1; i < 5; i += 1 )}§
     1171for ( 1 ®~® 5 )                                                 $\C{// for ( typeof(1) i = 1; i < 5; i += 1 )}$
    11711172\end{cfa}
    11721173\item
    11731174L ©~=©\index{~=@©~=©} H is explicit up-to inclusive range [L,H\R{]}.
    11741175\begin{cfa}
    1175 for ( 1 ®~=® 5 )                                                §\C{// for ( typeof(1) i = 1; i <= 5; i += 1 )}§
     1176for ( 1 ®~=® 5 )                                                $\C{// for ( typeof(1) i = 1; i <= 5; i += 1 )}$
    11761177\end{cfa}
    11771178\item
    11781179L ©-~©\index{-~@©-~©} H is explicit down-to exclusive range [H,L\R{)}, where L and H are implicitly interchanged to make the range down-to.
    11791180\begin{cfa}
    1180 for ( 1 ®-~® 5 )                                                §\C{// for ( typeof(1) i = 5; i > 0; i -= 1 )}§
     1181for ( 1 ®-~® 5 )                                                $\C{// for ( typeof(1) i = 5; i > 0; i -= 1 )}$
    11811182\end{cfa}
    11821183\item
    11831184L ©-~=©\index{-~=@©-~=©} H is explicit down-to inclusive range [H,L\R{]}, where L and H are implicitly interchanged to make the range down-to.
    11841185\begin{cfa}
    1185 for ( 1 ®-~=® 5 )                                               §\C{// for ( typeof(1) i = 5; i >= 0; i -= 1 )}§
     1186for ( 1 ®-~=® 5 )                                               $\C{// for ( typeof(1) i = 5; i >= 0; i -= 1 )}$
    11861187\end{cfa}
    11871188\item
    11881189©@© means put nothing in this field.
    11891190\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 */} )}§
     1191for ( i; 1 ~ ®@® ~ 2 )                                  $\C{// for ( typeof(1) i = 1; \R{/* empty */}; i += 2 )}$
     1192for ( i; 1 ~ 10 ~ ®@® )                                 $\C{// for ( typeof(1) i = 1; i < 10; \R{/* empty */} )}$
     1193for ( i; 1 ~ ®@® ~ ®@® )                                $\C{// for ( typeof(1) i = 1; /*empty*/; \R{/* empty */} )}$
    11931194\end{cfa}
    11941195L 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.
     
    11971198©:© means low another index.
    11981199\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 )}§
     1200for ( i; 5 ®:® j; 2 ~ 12 ~ 3 )                  $\C{// for ( typeof(i) i = 1, j = 2; i < 5 \&\& j < 12; i += 1, j += 3 )}$
    12001201\end{cfa}
    12011202\end{itemize}
    12021203\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):
    12031204\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!}}}§
     1205for ( i; 1 ~ 10 )                                               ${\C{// up range}$
     1206for ( i; 1 -~ 10 )                                              ${\C{// down range}$
     1207for ( i; ®10 -~ 1® )                                    ${\C{// \R{WRONG down range!}}}$
    12071208\end{cfa}
    12081209The 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.
     
    13601361Grouping heterogeneous data into an \newterm{aggregate} (structure/union) is a common programming practice, and aggregates may be nested:
    13611362\begin{cfa}
    1362 struct Person {                                                 §\C{// aggregate}§
    1363         struct Name {                                           §\C{// nesting}§
     1363struct Person {                                                 $\C{// aggregate}$
     1364        struct Name {                                           $\C{// nesting}$
    13641365                char first[20], last[20];
    13651366        } name;
    1366         struct Address {                                        §\C{// nesting}§
     1367        struct Address {                                        $\C{// nesting}$
    13671368                ...
    13681369        } address;
     
    13731374\begin{cfa}
    13741375Person p
    1375 ®p.®name; ®p.®address; ®p.®sex;                 §\C{// access containing fields}§
     1376®p.®name; ®p.®address; ®p.®sex;                 $\C{// access containing fields}$
    13761377\end{cfa}
    13771378which extends to multiple levels of qualification for nested aggregates and multiple aggregates.
    13781379\begin{cfa}
    13791380struct 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}$
    13821383\end{cfa}
    13831384Repeated aggregate qualification is tedious and makes code difficult to read.
     
    13881389\begin{cfa}
    13891390struct S {
    1390         struct §\R{\LstCommentStyle{/* unnamed */}}§  { int g,  h; } __attribute__(( aligned(64) ));
     1391        struct $\R{\LstCommentStyle{/* unnamed */}}$  { int g,  h; } __attribute__(( aligned(64) ));
    13911392        int tag;
    1392         union §\R{\LstCommentStyle{/* unnamed */}}§  {
     1393        union $\R{\LstCommentStyle{/* unnamed */}}$  {
    13931394                struct { char c1,  c2; } __attribute__(( aligned(128) ));
    13941395                struct { int i1,  i2; };
     
    14041405struct S {
    14051406        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;}$
    14081409        }
    14091410}
     
    14131414\begin{cfa}
    14141415struct T {
    1415         char ®m®;   int ®i®;   double ®n®;      §\C{// derived class variables}§
     1416        char ®m®;   int ®i®;   double ®n®;      $\C{// derived class variables}$
    14161417};
    14171418struct S : public T {
    1418         char ®c®;   int ®i®;   double ®d®;      §\C{// class variables}§
     1419        char ®c®;   int ®i®;   double ®d®;      $\C{// class variables}$
    14191420        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}$
    14231424        }
    14241425};
     
    14301431Hence, 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.
    14311432\begin{cfa}
    1432 void f( S & this ) ®with ( this )® {    §\C{// with statement}§
    1433         ®c®;   ®i®;   ®d®;                                      §\C{// this.c, this.i, this.d}§
     1433void f( S & this ) ®with ( this )® {    $\C{// with statement}$
     1434        ®c®;   ®i®;   ®d®;                                      $\C{// this.c, this.i, this.d}$
    14341435}
    14351436\end{cfa}
    14361437with the generality of opening multiple aggregate-parameters:
    14371438\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}§
     1439void 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}$
    14411442}
    14421443\end{cfa}
     
    14611462struct R { int ®i®; int j; double ®m®; } r, w;
    14621463with ( 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}$
    14701471}
    14711472\end{cfa}
     
    14751476\begin{cfa}
    14761477with ( r ) {
    1477         i;                                                                      §\C{// unambiguous, r.i}§
     1478        i;                                                                      $\C{// unambiguous, r.i}$
    14781479        with ( q ) {
    1479                 i;                                                              §\C{// unambiguous, q.i}§
     1480                i;                                                              $\C{// unambiguous, q.i}$
    14801481        }
    14811482}
     
    14841485A cast can also be used to disambiguate among overload variables in a ©with© \emph{expression}:
    14851486\begin{cfa}
    1486 with ( w ) { ... }                                              §\C{// ambiguous, same name and no context}§
    1487 with ( (Q)w ) { ... }                                   §\C{// unambiguous, cast}§
     1487with ( w ) { ... }                                              $\C{// ambiguous, same name and no context}$
     1488with ( (Q)w ) { ... }                                   $\C{// unambiguous, cast}$
    14881489\end{cfa}
    14891490Because 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©.
     
    14921493\begin{cfa}
    14931494void 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}$
    14951496}
    14961497\end{cfa}
     
    14981499To solve this problem, parameters \emph{not} explicitly opened are treated like an initialized aggregate:
    14991500\begin{cfa}
    1500 struct Params {                                                 §\C{// s explicitly opened so S \& s elided}§
     1501struct Params {                                                 $\C{// s explicitly opened so S \& s elided}$
    15011502        char c;
    15021503} params;
     
    15041505and implicitly opened \emph{after} a function-body open, to give them higher priority:
    15051506\begin{cfa}
    1506 void f( S & s, char ®c® ) with ( s ) ®with( §\emph{\R{params}}§ )® { // syntax not allowed, illustration only
     1507void f( S & s, char ®c® ) with ( s ) ®with( $\emph{\R{params}}$ )® { // syntax not allowed, illustration only
    15071508        s.c = ®c;®  i = 3;  d = 5.5;
    15081509}
     
    15371538
    15381539\begin{cfa}
    1539 exception_t E {}; §\C{// exception type}§
     1540exception_t E {}; $\C{// exception type}$
    15401541void f(...) {
    1541         ... throw E{}; ... §\C{// termination}§
    1542         ... throwResume E{}; ... §\C{// resumption}§
     1542        ... throw E{}; ... $\C{// termination}$
     1543        ... throwResume E{}; ... $\C{// resumption}$
    15431544}
    15441545try {
    15451546        f(...);
    1546 } catch( E e ; §boolean-predicate§ ) {  §\C{// termination handler}§
     1547} catch( E e ; $boolean-predicate$ ) {  $\C{// termination handler}$
    15471548        // recover and continue
    1548 } catchResume( E e ; §boolean-predicate§ ) { §\C{// resumption handler}§
     1549} catchResume( E e ; $boolean-predicate$ ) { $\C{// resumption handler}$
    15491550        // repair and return
    15501551} finally {
     
    16231624For example, a routine returning a \Index{pointer} to an array of integers is defined and used in the following way:
    16241625\begin{cfa}
    1625 int ®(*®f®())[®5®]® {...}; §\C{// definition}§
    1626  ... ®(*®f®())[®3®]® += 1; §\C{// usage}§
     1626int ®(*®f®())[®5®]® {...}; $\C{// definition}$
     1627 ... ®(*®f®())[®3®]® += 1; $\C{// usage}$
    16271628\end{cfa}
    16281629Essentially, the return type is wrapped around the routine name in successive layers (like an \Index{onion}).
     
    18691870For example, \Index*{Algol68}~\cite{Algol68} infers pointer dereferencing to select the best meaning for each pointer usage
    18701871\begin{cfa}
    1871 p2 = p1 + x; §\C{// compiler infers *p2 = *p1 + x;}§
     1872p2 = p1 + x; $\C{// compiler infers *p2 = *p1 + x;}$
    18721873\end{cfa}
    18731874Algol68 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.
     
    18771878In C, objects of pointer type always manipulate the pointer object's address:
    18781879\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}§
     1880p1 = p2; $\C{// p1 = p2\ \ rather than\ \ *p1 = *p2}$
     1881p2 = p1 + x; $\C{// p2 = p1 + x\ \ rather than\ \ *p2 = *p1 + x}$
    18811882\end{cfa}
    18821883even though the assignment to ©p2© is likely incorrect, and the programmer probably meant:
    18831884\begin{cfa}
    1884 p1 = p2; §\C{// pointer address assignment}§
    1885 ®*®p2 = ®*®p1 + x; §\C{// pointed-to value assignment / operation}§
     1885p1 = p2; $\C{// pointer address assignment}$
     1886®*®p2 = ®*®p1 + x; $\C{// pointed-to value assignment / operation}$
    18861887\end{cfa}
    18871888The 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©).
     
    19001901\begin{cfa}
    19011902int 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}$
     1907r2 = ((r1 + r2) * (r3 - r1)) / (r3 - 15); $\C{// implicit dereferencing}$
    19071908\end{cfa}
    19081909Except for auto-dereferencing by the compiler, this reference example is the same as the previous pointer example.
     
    19191920For a \CFA reference type, the cancellation on the left-hand side of assignment leaves the reference as an address (\Index{lvalue}):
    19201921\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}$
    19221923\end{cfa}
    19231924Similarly, the address of a reference can be obtained for assignment or computation (\Index{rvalue}):
    19241925\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}$
    19261927\end{cfa}
    19271928Cancellation\index{cancellation!pointer/reference}\index{pointer!cancellation} works to arbitrary depth.
     
    19311932int x, *p1 = &x, **p2 = &p1, ***p3 = &p2,
    19321933                 &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}$
     1935r3 = 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}$
    19401941\end{cfa}
    19411942Furthermore, both types are equally performant, as the same amount of dereferencing occurs for both types.
     
    19441945As for a pointer type, a reference type may have qualifiers:
    19451946\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}§
     1947const int cx = 5; $\C{// cannot change cx;}$
     1948const int & cr = cx; $\C{// cannot change what cr points to}$
     1949®&®cr = &cx; $\C{// can change cr}$
     1950cr = 7; $\C{// error, cannot change cx}$
     1951int & const rc = x; $\C{// must be initialized}$
     1952®&®rc = &x; $\C{// error, cannot change rc}$
     1953const int & const crc = cx; $\C{// must be initialized}$
     1954crc = 7; $\C{// error, cannot change cx}$
     1955®&®crc = &cx; $\C{// error, cannot change crc}$
    19551956\end{cfa}
    19561957Hence, 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}:
    19571958\begin{cfa}
    1958 int & const cr = *0; §\C{// where 0 is the int * zero}§
     1959int & const cr = *0; $\C{// where 0 is the int * zero}$
    19591960\end{cfa}
    19601961Note, constant reference-types do not prevent \Index{addressing errors} because of explicit storage-management:
     
    19631964cr = 5;
    19641965free( &cr );
    1965 cr = 7; §\C{// unsound pointer dereference}§
     1966cr = 7; $\C{// unsound pointer dereference}$
    19661967\end{cfa}
    19671968
     
    19711972\begin{cquote}
    19721973\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}}     \\
    19741975\begin{cfa}
    19751976const int * ®const® * ®const® ccp;
     
    19871988Finally, like pointers, references are usable and composable with other type operators and generators.
    19881989\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}§
     1990int w, x, y, z, & ar[3] = { x, y, z }; $\C{// initialize array of references}$
     1991&ar[1] = &w; $\C{// change reference array element}$
     1992typeof( ar[1] ) p; $\C{// (gcc) is int, \ie the type of referenced object}$
     1993typeof( &ar[1] ) q; $\C{// (gcc) is int \&, \ie the type of reference}$
     1994sizeof( ar[1] ) == sizeof( int ); $\C{// is true, \ie the size of referenced object}$
     1995sizeof( &ar[1] ) == sizeof( int *) $\C{// is true, \ie the size of a reference}$
    19951996\end{cfa}
    19961997
     
    20092010Therefore, for pointer/reference initialization, the initializing value must be an address not a value.
    20102011\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}§
     2012int * p = &x; $\C{// assign address of x}$
     2013®int * p = x;® $\C{// assign value of x}$
     2014int & r = x; $\C{// must have address of x}$
    20142015\end{cfa}
    20152016Like 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).
     
    20202021Similarly, 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.
    20212022\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}§
     2023int & f( int & r ); $\C{// reference parameter and return}$
     2024z = f( x ) + f( y ); $\C{// reference operator added, temporaries needed for call results}$
    20242025\end{cfa}
    20252026Within routine ©f©, it is possible to change the argument by changing the corresponding parameter, and parameter ©r© can be locally reassigned within ©f©.
     
    20482049void f( int & r );
    20492050void 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}§
     2051f( 3 );                   g( ®&®3 ); $\C{// compiler implicit generates temporaries}$
     2052f( x + y );             g( ®&®(x + y) ); $\C{// compiler implicit generates temporaries}$
    20522053\end{cfa}
    20532054Essentially, there is an implicit \Index{rvalue} to \Index{lvalue} conversion in this case.\footnote{
     
    20602061\begin{cfa}
    20612062void 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}§
     2063void (* fp)( int ); $\C{// routine pointer}$
     2064fp = f; $\C{// reference initialization}$
     2065fp = &f; $\C{// pointer initialization}$
     2066fp = *f; $\C{// reference initialization}$
     2067fp(3); $\C{// reference invocation}$
     2068(*fp)(3); $\C{// pointer invocation}$
    20682069\end{cfa}
    20692070While 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.
    20702071Instead, a routine object should be referenced by a ©const© reference:
    20712072\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}$
     2074fr = ... $\C{// error, cannot change code}$
     2075&fr = ...; $\C{// changing routine reference}$
     2076fr( 3 ); $\C{// reference call to f}$
     2077(*fr)(3); $\C{// error, incorrect type}$
    20772078\end{cfa}
    20782079because the value of the routine object is a routine literal, \ie the routine code is normally immutable during execution.\footnote{
     
    20962097int x, * px, ** ppx, *** pppx, **** ppppx;
    20972098int & 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)}§
     2099x = rrrx; $\C[2.0in]{// rrrx is an lvalue with type int \&\&\& (equivalent to x)}$
     2100px = &rrrx; $\C{// starting from rrrx, \&rrrx is an rvalue with type int *\&\&\& (\&x)}$
     2101ppx = &&rrrx; $\C{// starting from \&rrrx, \&\&rrrx is an rvalue with type int **\&\& (\&rx)}$
     2102pppx = &&&rrrx; $\C{// starting from \&\&rrrx, \&\&\&rrrx is an rvalue with type int ***\& (\&rrx)}$
     2103ppppx = &&&&rrrx; $\C{// starting from \&\&\&rrrx, \&\&\&\&rrrx is an rvalue with type int **** (\&rrrx)}$
    21032104\end{cfa}
    21042105The following example shows the second rule applied to different \Index{lvalue} contexts:
     
    21062107int x, * px, ** ppx, *** pppx;
    21072108int & 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)}§
     2109rrrx = 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$
    21122113\end{cfa}
    21132114
     
    21222123\begin{cfa}
    21232124int x;
    2124 x + 1;                                          §\C{// lvalue variable (int) converts to rvalue for expression}§
     2125x + 1; $\C[2.0in]{// lvalue variable (int) converts to rvalue for expression}$
    21252126\end{cfa}
    21262127An rvalue has no type qualifiers (©cv©), so the lvalue qualifiers are dropped.
     
    21322133\begin{cfa}
    21332134int x, &r = x, f( int p );
    2134 x = ®r® + f( ®r® );                     §\C{// lvalue reference converts to rvalue}§
     2135x = ®r® + f( ®r® ); $\C{// lvalue reference converts to rvalue}$
    21352136\end{cfa}
    21362137An rvalue has no type qualifiers (©cv©), so the reference qualifiers are dropped.
     
    21392140lvalue to reference conversion: \lstinline[deletekeywords=lvalue]{lvalue-type cv1 T} converts to ©cv2 T &©, which allows implicitly converting variables to references.
    21402141\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 \&)}§
     2142int x, &r = ®x®, f( int & p ); $\C{// lvalue variable (int) convert to reference (int \&)}$
     2143f( ®x® ); $\C{// lvalue variable (int) convert to reference (int \&)}\CRT$
    21432144\end{cfa}
    21442145Conversion can restrict a type, where ©cv1© $\le$ ©cv2©, \eg passing an ©int© to a ©const volatile int &©, which has low cost.
     
    21502151\begin{cfa}
    21512152int 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 \&)}§
     2153f( ®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$
    21542155\end{cfa}
    21552156In both case, modifications to the temporary are inaccessible (\Index{warning}).
     
    23182319
    23192320
    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 string
    2354 s = string( 5 );                        // converts int to string
    2355 s = string( 5.5 );                      // converts double to string
    2356 \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 p
    2364 \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 string
    2372         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 string
    2377         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 x
    2398 abc
    2399 
    2400 abc
    2401 
    2402 45
    2403 45
    2404 -9223372036854775808
    2405 18446744073709551615
    2406 5.5
    2407 5.5
    2408 5.5+3.4i
    2409 5.5+3.4i
    2410 
    2411 5.5+
    2412 5.5+3.4i
    2413 
    2414 5.5+3.4i 5.5+3.4i
    2415 
    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© operation
    2451 \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 reference
    2501 // e is a substring result passed by value
    2502 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© operation
    2538 \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© operation
    2563 \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© operation
    2577 \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© operation
    2618 \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 blanks
    2624 s = string( "   ABC" ).trim( " " );                     §\C{// s is assigned "ABC",}§
    2625 // remove trailing blanks
    2626 s = string( "ABC   " ).trim( " ", last );       §\C{// s is assigned "ABC",}§
    2627 \end{cfa}
    2628 
    2629 The ©translate© operation
    2630 \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 case
    2638 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 case
    2643 peter = peter.translate( "abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZ" );
    2644                         // peter is assigned "PETER"
    2645 \end{cfa}
    2646 
    2647 The ©replace© operation
    2648 \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 
    26962321\section{Enumeration}
    26972322
     
    27072332Hence, enums may be overloaded with variable, enum, and function names.
    27082333\begin{cfa}
    2709 int Foo;                        §\C{// type/variable separate namespaces}§
     2334int Foo;                        $\C{// type/variable separate namespaces}$
    27102335enum Foo { Bar };
    2711 enum Goo { Bar };       §\C[1.75in]{// overload Foo.Bar}§
    2712 double Bar;                     §\C{// overload Foo.Bar, Goo.Bar}\CRT§
     2336enum Goo { Bar };       $\C[1.75in]{// overload Foo.Bar}$
     2337double Bar;                     $\C{// overload Foo.Bar, Goo.Bar}\CRT$
    27132338\end{cfa}
    27142339An anonymous enumeration injects enums with specific values into a scope.
     
    27832408The following examples illustrate the difference between the enumeration type and the type of its enums.
    27842409\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§
     2410Math m = PI;    $\C[1.5in]{// allowed}$
     2411double d = PI;  $\C{// allowed, conversion to base type}$
     2412m = E;                  $\C{// allowed}$
     2413m = Alph;               $\C{// {\color{red}disallowed}}$
     2414m = 3.141597;   $\C{// {\color{red}disallowed}}$
     2415d = m;                  $\C{// allowed}$
     2416d = Alph;               $\C{// {\color{red}disallowed}}$
     2417Letter l = A;   $\C{// allowed}$
     2418Greek g = Alph; $\C{// allowed}$
     2419l = Alph;               $\C{// allowed, conversion to base type}$
     2420g = A;                  $\C{// {\color{red}disallowed}}\CRT$
    27962421\end{cfa}
    27972422
     
    28832508\begin{cfa}
    28842509®[ int o1, int o2, char o3 ]® f( int i1, char i2, char i3 ) {
    2885         §\emph{routine body}§
     2510        $\emph{routine body}$
    28862511}
    28872512\end{cfa}
     
    28942519Declaration qualifiers can only appear at the start of a routine definition, \eg:
    28952520\begin{cfa}
    2896 ®extern® [ int x ] g( int y ) {§\,§}
     2521®extern® [ int x ] g( int y ) {$\,$}
    28972522\end{cfa}
    28982523Lastly, if there are no output parameters or input parameters, the brackets and/or parentheses must still be specified;
    28992524in 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:
    29002525\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}$
    29032528\end{cfa}
    29042529
     
    29182543\begin{cfa}
    29192544typedef int foo;
    2920 int f( int (* foo) ); §\C{// foo is redefined as a parameter name}§
     2545int f( int (* foo) ); $\C{// foo is redefined as a parameter name}$
    29212546\end{cfa}
    29222547The 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.
     
    29262551C-style declarations can be used to declare parameters for \CFA style routine definitions, \eg:
    29272552\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}$
    29302555\end{cfa}
    29312556The 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:
    29322557\begin{cfa}
    29332558#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 ] )}§
     2559int 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 ] )}$
    29362561\end{cfa}
    29372562Again, programmers are highly encouraged to use one declaration form or the other, rather than mixing the forms.
     
    29552580        int z;
    29562581        ... x = 0; ... y = z; ...
    2957         ®return;® §\C{// implicitly return x, y}§
     2582        ®return;® $\C{// implicitly return x, y}$
    29582583}
    29592584\end{cfa}
     
    29652590[ int x, int y ] f() {
    29662591        ...
    2967 } §\C{// implicitly return x, y}§
     2592} $\C{// implicitly return x, y}$
    29682593\end{cfa}
    29692594In this case, the current values of ©x© and ©y© are returned to the calling routine just as if a ©return© had been encountered.
     
    29742599[ int x, int y ] f( int, x, int y ) {
    29752600        ...
    2976 } §\C{// implicitly return x, y}§
     2601} $\C{// implicitly return x, y}$
    29772602\end{cfa}
    29782603This notation allows the compiler to eliminate temporary variables in nested routine calls.
    29792604\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}$
    29812606int a, b;
    29822607[a, b] = f( f( f( a, b ) ) );
     
    29922617as well, parameter names are optional, \eg:
    29932618\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}$
    29982623\end{cfa}
    29992624This syntax allows a prototype declaration to be created by cutting and pasting source text from the routine definition header (or vice versa).
     
    30012626\begin{cfa}
    30022627C :             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; }
    30042629\end{cfa}
    30052630\CFA allows the last routine in the list to define its body.
     
    30162641The syntax for pointers to \CFA routines specifies the pointer name on the right, \eg:
    30172642\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$
    30222647\end{cfa}
    30232648While parameter names are optional, \emph{a routine name cannot be specified};
    30242649for example, the following is incorrect:
    30252650\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}$
    30272652\end{cfa}
    30282653
     
    30472672whereas a named (keyword) call may be:
    30482673\begin{cfa}
    3049 p( z : 3, x : 4, y : 7 );  §\C{// rewrite \(\Rightarrow\) p( 4, 7, 3 )}§
     2674p( z : 3, x : 4, y : 7 );  $\C{// rewrite \(\Rightarrow\) p( 4, 7, 3 )}$
    30502675\end{cfa}
    30512676Here the order of the arguments is unimportant, and the names of the parameters are used to associate argument values with the corresponding parameters.
     
    30642689For example, the following routine prototypes and definition are all valid.
    30652690\begin{cfa}
    3066 void p( int, int, int ); §\C{// equivalent prototypes}§
     2691void p( int, int, int ); $\C{// equivalent prototypes}$
    30672692void p( int x, int y, int z );
    30682693void p( int y, int x, int z );
    30692694void p( int z, int y, int x );
    3070 void p( int q, int r, int s ) {} §\C{// match with this definition}§
     2695void p( int q, int r, int s ) {} $\C{// match with this definition}$
    30712696\end{cfa}
    30722697Forcing matching parameter names in routine prototypes with corresponding routine definitions is possible, but goes against a strong tradition in C programming.
     
    30802705int f( int x, double y );
    30812706
    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}§
     2707f( j : 3, i : 4 ); $\C{// 1st f}$
     2708f( x : 7, y : 8.1 ); $\C{// 2nd f}$
     2709f( 4, 5 );  $\C{// ambiguous call}$
    30852710\end{cfa}
    30862711However, named arguments compound routine resolution in conjunction with conversions:
    30872712\begin{cfa}
    3088 f( i : 3, 5.7 ); §\C{// ambiguous call ?}§
     2713f( i : 3, 5.7 ); $\C{// ambiguous call ?}$
    30892714\end{cfa}
    30902715Depending on the cost associated with named arguments, this call could be resolvable or ambiguous.
     
    31002725the allowable positional calls are:
    31012726\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 )}§
     2727p(); $\C{// rewrite \(\Rightarrow\) p( 1, 2, 3 )}$
     2728p( 4 ); $\C{// rewrite \(\Rightarrow\) p( 4, 2, 3 )}$
     2729p( 4, 4 ); $\C{// rewrite \(\Rightarrow\) p( 4, 4, 3 )}$
     2730p( 4, 4, 4 ); $\C{// rewrite \(\Rightarrow\) p( 4, 4, 4 )}$
    31062731// 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 )}§
     2732p(  , 4, 4 ); $\C{// rewrite \(\Rightarrow\) p( 1, 4, 4 )}$
     2733p( 4,  , 4 ); $\C{// rewrite \(\Rightarrow\) p( 4, 2, 4 )}$
     2734p( 4, 4,   ); $\C{// rewrite \(\Rightarrow\) p( 4, 4, 3 )}$
     2735p( 4,  ,   ); $\C{// rewrite \(\Rightarrow\) p( 4, 2, 3 )}$
     2736p(  , 4,   ); $\C{// rewrite \(\Rightarrow\) p( 1, 4, 3 )}$
     2737p(  ,  , 4 ); $\C{// rewrite \(\Rightarrow\) p( 1, 2, 4 )}$
     2738p(  ,  ,   ); $\C{// rewrite \(\Rightarrow\) p( 1, 2, 3 )}$
    31142739\end{cfa}
    31152740Here the missing arguments are inserted from the default values in the parameter list.
     
    31352760Default values may only appear in a prototype versus definition context:
    31362761\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}§
     2762void p( int x, int y = 2, int z = 3 ); $\C{// prototype: allowed}$
     2763void p( int, int = 2, int = 3 ); $\C{// prototype: allowed}$
     2764void p( int x, int y = 2, int z = 3 ) {} $\C{// definition: not allowed}$
    31402765\end{cfa}
    31412766The reason for this restriction is to allow separate compilation.
     
    31522777\begin{cfa}
    31532778p( 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 */, ... );}§
     2779p( 1, 4, 5, 6, z : 3, y : 2 ); $\C{// assume p( /* positional */, ... , /* named */ );}$
     2780p( 1, z : 3, y : 2, 4, 5, 6 ); $\C{// assume p( /* positional */, /* named */, ... );}$
    31562781\end{cfa}
    31572782In 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.
     
    31622787\begin{cfa}
    31632788void 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 */, ... );}§
     2789p( 1, 4, 5, 6, z : 3 ); $\C{// assume p( /* positional */, ... , /* named */ );}$
     2790p( 1, z : 3, 4, 5, 6 ); $\C{// assume p( /* positional */, /* named */, ... );}$
    31662791\end{cfa}
    31672792The first call is an error because arguments 4 and 5 are actually positional not ellipse arguments;
     
    31932818Furthermore, overloading cannot handle accessing default arguments in the middle of a positional list, via a missing argument, such as:
    31942819\begin{cfa}
    3195 p( 1, /* default */, 5 ); §\C{// rewrite \(\Rightarrow\) p( 1, 2, 5 )}§
     2820p( 1, /* default */, 5 ); $\C{// rewrite \(\Rightarrow\) p( 1, 2, 5 )}$
    31962821\end{cfa}
    31972822
     
    32062831\begin{cfa}
    32072832struct {
    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}$
    32142839};
    32152840\end{cfa}
     
    32192844\begin{cfa}
    32202845struct {
    3221         int , , ; §\C{// 3 unnamed fields}§
     2846        int , , ; $\C{// 3 unnamed fields}$
    32222847}
    32232848\end{cfa}
     
    33132938const unsigned int size = 5;
    33142939int 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}$
     2941qsort( ia, size ); $\C{// sort ascending order using builtin ?<?}$
    33172942{
    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}$
    33202945}
    33212946\end{cfa}
     
    33252950The following program in undefined in \CFA (and Indexc{gcc})
    33262951\begin{cfa}
    3327 [* [int]( int )] foo() { §\C{// int (* foo())( int )}§
     2952[* [int]( int )] foo() { $\C{// int (* foo())( int )}$
    33282953        int ®i® = 7;
    33292954        int bar( int p ) {
    3330                 ®i® += 1; §\C{// dependent on local variable}§
     2955                ®i® += 1; $\C{// dependent on local variable}$
    33312956                sout | ®i®;
    33322957        }
    3333         return bar; §\C{// undefined because of local dependence}§
     2958        return bar; $\C{// undefined because of local dependence}$
    33342959}
    33352960int main() {
    3336         * [int]( int ) fp = foo(); §\C{// int (* fp)( int )}§
     2961        * [int]( int ) fp = foo(); $\C{// int (* fp)( int )}$
    33372962        sout | fp( 3 );
    33382963}
     
    33472972In C and \CFA, lists of elements appear in several contexts, such as the parameter list of a routine call.
    33482973\begin{cfa}
    3349 f( ®2, x, 3 + i® ); §\C{// element list}§
     2974f( ®2, x, 3 + i® ); $\C{// element list}$
    33502975\end{cfa}
    33512976A list of elements is called a \newterm{tuple}, and is different from a \Index{comma expression}.
     
    33622987For example, consider C's \Indexc{div} function, which returns the quotient and remainder for a division of an integer value.
    33632988\begin{cfa}
    3364 typedef struct { int quot, rem; } div_t;        §\C[7cm]{// from include stdlib.h}§
     2989typedef struct { int quot, rem; } div_t;        $\C[7cm]{// from include stdlib.h}$
    33652990div_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}§
     2991div_t qr = div( 13, 5 ); $\C{// return quotient/remainder aggregate}$
     2992printf( "%d %d\n", qr.quot, qr.rem ); $\C{// print quotient/remainder}$
    33682993\end{cfa}
    33692994This approach requires a name for the return type and fields, where \Index{naming} is a common programming-language issue.
     
    33753000For example, consider C's \Indexc{modf} function, which returns the integral and fractional part of a floating value.
    33763001\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}§
     3002double modf( double x, double * i ); $\C{// from include math.h}$
     3003double intp, frac = modf( 13.5, &intp ); $\C{// return integral and fractional components}$
     3004printf( "%g %g\n", intp, frac ); $\C{// print integral/fractional components}$
    33803005\end{cfa}
    33813006This approach requires allocating storage for the return values, which complicates the call site with a sequence of variable declarations leading to the call.
     
    34043029When 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.
    34053030\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}§
     3031void g( int, int ); $\C{// 1}$
     3032void g( double, double ); $\C{// 2}$
     3033g( div( 13, 5 ) ); $\C{// select 1}$
     3034g( modf( 13.5 ) ); $\C{// select 2}$
    34103035\end{cfa}
    34113036In this case, there are two overloaded ©g© routines.
     
    34163041The previous examples can be rewritten passing the multiple returned-values directly to the ©printf© function call.
    34173042\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}$
     3044printf( "%d %d\n", div( 13, 5 ) ); $\C{// print quotient/remainder}$
     3045
     3046[ double, double ] modf( double x ); $\C{// from include math}$
     3047printf( "%g %g\n", modf( 13.5 ) ); $\C{// print integral/fractional components}$
    34233048\end{cfa}
    34243049This 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.
     
    34303055\begin{cfa}
    34313056int 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}$
     3058printf( "%d %d\n", quot, rem ); $\C{// print quotient/remainder}\CRT$
    34343059\end{cfa}
    34353060Here, the multiple return-values are matched in much the same way as passing multiple return-values to multiple parameters in a call.
     
    34603085In \CFA, it is possible to overcome this restriction by declaring a \newterm{tuple variable}.
    34613086\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}$
     3088printf( "%d %d\n", ®qr® ); $\C{// print quotient/remainder}$
    34643089\end{cfa}
    34653090It is now possible to match the multiple return-values to a single variable, in much the same way as \Index{aggregation}.
     
    34673092One way to access the individual components of a tuple variable is with assignment.
    34683093\begin{cfa}
    3469 [ quot, rem ] = qr; §\C{// assign multiple variables}§
     3094[ quot, rem ] = qr; $\C{// assign multiple variables}$
    34703095\end{cfa}
    34713096
     
    34903115[int, double] * p;
    34913116
    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}§
     3117int y = x.0; $\C{// access int component of x}$
     3118y = f().1; $\C{// access int component of f}$
     3119p->0 = 5; $\C{// access int component of tuple pointed-to by p}$
     3120g( x.1, x.0 ); $\C{// rearrange x to pass to g}$
     3121double z = [ x, f() ].0.1; $\C{// access second component of first component of tuple expression}$
    34973122\end{cfa}
    34983123Tuple-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.
     
    35623187double y;
    35633188[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}$
     3191z = 10;                                                         $\C{// mass assignment}$
     3192z = [x, y]; $\C{// multiple assignment}$
    35683193\end{cfa}
    35693194Let $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.
     
    35733198\begin{cfa}
    35743199[ 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}$
    35763201\end{cfa}
    35773202Multiple assignment assigns $R_i$ to $L_i$ for each $i$.
     
    36093234        double c, d;
    36103235        [ 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}$
    36123237\end{cfa}
    36133238The 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.
     
    36223247\begin{cfa}
    36233248struct 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}§
     3249void ?{}(S *); $\C{// (1)}$
     3250void ?{}(S *, int); $\C{// (2)}$
     3251void ?{}(S * double); $\C{// (3)}$
     3252void ?{}(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}$
    36323257\end{cfa}
    36333258In 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)©.
     
    36703295A member-access tuple may be used anywhere a tuple can be used, \eg:
    36713296\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 )}§
     3297s.[ y, z, x ] = [ 3, 3.2, 'x' ]; $\C{// equivalent to s.x = 'x', s.y = 3, s.z = 3.2}$
     3298f( s.[ y, z ] ); $\C{// equivalent to f( s.y, s.z )}$
    36743299\end{cfa}
    36753300Note, the fields appearing in a record-field tuple may be specified in any order;
     
    36813306void f( double, long );
    36823307
    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 ]}§
     3308f( x.[ 0, 3 ] ); $\C{// f( x.0, x.3 )}$
     3309x.[ 0, 1 ] = x.[ 1, 0 ]; $\C{// [ x.0, x.1 ] = [ x.1, x.0 ]}$
    36853310[ long, int, long ] y = x.[ 2, 0, 2 ];
    36863311\end{cfa}
     
    36993324\begin{cfa}
    37003325[ 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}$
    37023327\end{cfa}
    37033328
     
    37123337That 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.
    37133338\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)}§
     3339int f(); $\C{// (1)}$
     3340double f(); $\C{// (2)}$
     3341
     3342f(); $\C{// ambiguous - (1),(2) both equally viable}$
     3343(int)f(); $\C{// choose (2)}$
    37193344\end{cfa}
    37203345Since casting is a fundamental operation in \CFA, casts need to be given a meaningful interpretation in the context of tuples.
     
    37243349void g();
    37253350
    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}$
    37283353
    37293354struct 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}$
    37313356\end{cfa}
    37323357In C, line 4 is a valid cast, which calls ©f© and discards its result.
     
    37443369        [int, [int, int], int] g();
    37453370
    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}$
    37513376\end{cfa}
    37523377
     
    38083433void f([int, int], int, int);
    38093434
    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}§
     3435f([0, 0], 0, 0); $\C{// no cost}$
     3436f(0, 0, 0, 0); $\C{// cost for structuring}$
     3437f([0, 0,], [0, 0]); $\C{// cost for flattening}$
     3438f([0, 0, 0], 0); $\C{// cost for flattening and structuring}$
    38143439\end{cfa}
    38153440
     
    38753500[ unsigned int, char ]
    38763501[ double, double, double ]
    3877 [ * int, int * ] §\C{// mix of CFA and ANSI}§
     3502[ * int, int * ] $\C{// mix of CFA and ANSI}$
    38783503[ * [ 5 ] int, * * char, * [ [ int, int ] ] (int, int) ]
    38793504\end{cfa}
     
    38823507Examples of declarations using tuple types are:
    38833508\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}$
    38863511[ [ int, int ] ] z ([ int, int ]);
    38873512\end{cfa}
     
    39003525[ int, int ] w1;
    39013526[ 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}$
    39043529f( [ 1, 2, 3 ] );
    39053530f( w1, 3 );
     
    39823607[ int, int, int, int ] w = [ 1, 2, 3, 4 ];
    39833608int x = 5;
    3984 [ x, w ] = [ w, x ]; §\C{// all four tuple coercions}§
     3609[ x, w ] = [ w, x ]; $\C{// all four tuple coercions}$
    39853610\end{cfa}
    39863611Starting on the right-hand tuple in the last assignment statement, w is opened, producing a tuple of four values;
     
    40723697both these examples produce indeterminate results:
    40733698\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}§
     3699f( 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}$
    40763701\end{cfa}
    40773702
     
    41723797\begin{cfa}
    41733798[int, [ int, int ] ] t1 = [ 1, [ 2, 3 ] ], t2 = [ 4, [ 5, 6 ] ];
    4174 sout | t1 | t2; §\C{// print tuples}§
     3799sout | t1 | t2; $\C{// print tuples}$
    41753800\end{cfa}
    41763801\begin{cfa}[showspaces=true,aboveskip=0pt]
     
    42563881
    42573882int main( int argc, char * argv[] ) {
    4258         ®ifstream® in  = stdin;                                 §\C{// copy default files}§
     3883        ®ifstream® in  = stdin;                                 $\C{// copy default files}$
    42593884        ®ofstream® out = stdout;
    42603885
     
    42623887                choose ( argc ) {
    42633888                  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}$
    42673892                  default:
    42683893                        ®exit® | "Usage" | argv[0] | "[ input-file (default stdin) "
    42693894                                   "[ output-file (default stdout) ] ]";
    42703895                } // 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}$
    42723897                ®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}$
    42753900                ®exit® | "Unable to open output file" | argv[2];
    42763901        } // try
    42773902
    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}$
    42803905        char ch;
    4281         for () {                                                                §\C{// read/write characters}§
     3906        for () {                                                                $\C{// read/write characters}$
    42823907                in | ch;
    4283           if ( eof( in ) ) break;                               §\C{// eof ?}§
     3908          if ( eof( in ) ) break;                               $\C{// eof ?}$
    42843909                out | ch;
    42853910        } // for
     
    43283953// *********************************** ofstream ***********************************
    43293954
    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©!©?{}©}§
     3955bool fail( ofstream & );$\indexc{fail}\index{ofstream@©ofstream©!©fail©}$
     3956void clear( ofstream & );$\indexc{clear}\index{ofstream@©ofstream©!©clear©}$
     3957int flush( ofstream & );$\indexc{flush}\index{ofstream@©ofstream©!©flush©}$
     3958void open( ofstream &, const char name[], const char mode[] = "w" );$\indexc{open}\index{ofstream@©ofstream©!©open©}$
     3959void close( ofstream & );$\indexc{close}\index{ofstream@©ofstream©!©close©}$
     3960ofstream & write( ofstream &, const char data[], size_t size );$\indexc{write}\index{ofstream@©ofstream©!©write©}$
     3961
     3962void ?{}( ofstream & );$\index{ofstream@©ofstream©!©?{}©}$
    43383963void ?{}( ofstream &, const char name[], const char mode[] = "w" );
    4339 void ^?{}( ofstream & );§\index{ofstream@©ofstream©!©^?{}©}§
     3964void ^?{}( ofstream & );$\index{ofstream@©ofstream©!©^?{}©}$
    43403965
    43413966// *********************************** ifstream ***********************************
    43423967
    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©!©?{}©}§
     3968bool fail( ifstream & is );$\indexc{fail}\index{ifstream@©ifstream©!©fail©}$
     3969void clear( ifstream & );$\indexc{clear}\index{ifstream@©ifstream©!©clear©}$
     3970bool eof( ifstream & is );$\indexc{eof}\index{ifstream@©ifstream©!©eof©}$
     3971void open( ifstream & is, const char name[], const char mode[] = "r" );$\indexc{open}\index{ifstream@©ifstream©!©open©}$
     3972void close( ifstream & is );$\indexc{close}\index{ifstream@©ifstream©!©close©}$
     3973ifstream & read( ifstream & is, char data[], size_t size );$\indexc{read}\index{ifstream@©ifstream©!©read©}$
     3974ifstream & ungetc( ifstream & is, char c );$\indexc{unget}\index{ifstream@©ifstream©!©unget©}$
     3975
     3976void ?{}( ifstream & is );$\index{ifstream@©ifstream©!©?{}©}$
    43523977void ?{}( ifstream & is, const char name[], const char mode[] = "r" );
    4353 void ^?{}( ifstream & is );§\index{ifstream@©ifstream©!©^?{}©}§
     3978void ^?{}( ifstream & is );$\index{ifstream@©ifstream©!©^?{}©}$
    43543979\end{cfa}
    43553980\caption{Stream Functions}
     
    44384063The separator string can be at most 16 characters including the ©'\0'© string terminator (15 printable characters).
    44394064\begin{cfa}[belowskip=0pt]
    4440 sepSet( sout, ", $\LstStringStyle{\textdollar}$" ); §\C{// set separator from " " to ", \$"}§
     4065sepSet( sout, ", $\LstStringStyle{\textdollar}$" ); $\C{// set separator from " " to ", \$"}$
    44414066sout | 1 | 2 | 3 | " \"" | ®sepVal® | "\"";
    44424067\end{cfa}
     
    44454070\end{cfa}
    44464071\begin{cfa}[belowskip=0pt]
    4447 sepSet( sout, " " ); §\C{// reset separator to " "}§
     4072sepSet( sout, " " ); $\C{// reset separator to " "}$
    44484073sout | 1 | 2 | 3 | " \"" | ®sepGet( sout )® | "\"";
    44494074\end{cfa}
     
    44534078©sepGet© can be used to store a separator and then restore it:
    44544079\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}§
     4080char store[®sepSize®]; $\C{// sepSize is the maximum separator size}$
     4081strcpy( store, sepGet( sout ) ); $\C{// copy current separator}$
     4082sepSet( sout, "_" ); $\C{// change separator to underscore}$
    44584083sout | 1 | 2 | 3;
    44594084\end{cfa}
     
    44624087\end{cfa}
    44634088\begin{cfa}[belowskip=0pt]
    4464 sepSet( sout, store ); §\C{// change separator back to original}§
     4089sepSet( sout, store ); $\C{// change separator back to original}$
    44654090sout | 1 | 2 | 3;
    44664091\end{cfa}
     
    44734098The tuple separator-string can be at most 16 characters including the ©'\0'© string terminator (15 printable characters).
    44744099\begin{cfa}[belowskip=0pt]
    4475 sepSetTuple( sout, " " ); §\C{// set tuple separator from ", " to " "}§
     4100sepSetTuple( sout, " " ); $\C{// set tuple separator from ", " to " "}$
    44764101sout | t1 | t2 | " \"" | ®sepTupleVal® | "\"";
    44774102\end{cfa}
     
    44804105\end{cfa}
    44814106\begin{cfa}[belowskip=0pt]
    4482 sepSetTuple( sout, ", " ); §\C{// reset tuple separator to ", "}§
     4107sepSetTuple( sout, ", " ); $\C{// reset tuple separator to ", "}$
    44834108sout | t1 | t2 | " \"" | ®sepGetTuple( sout )® | "\"";
    44844109\end{cfa}
     
    44914116\Indexc{sepOff}\index{manipulator!sepOff@©sepOff©} and \Indexc{sepOn}\index{manipulator!sepOn@©sepOn©} globally toggle printing the separator.
    44924117\begin{cfa}[belowskip=0pt]
    4493 sout | ®sepOff® | 1 | 2 | 3; §\C{// turn off implicit separator}§
     4118sout | ®sepOff® | 1 | 2 | 3; $\C{// turn off implicit separator}$
    44944119\end{cfa}
    44954120\begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
     
    44974122\end{cfa}
    44984123\begin{cfa}[belowskip=0pt]
    4499 sout | ®sepOn® | 1 | 2 | 3; §\C{// turn on implicit separator}§
     4124sout | ®sepOn® | 1 | 2 | 3; $\C{// turn on implicit separator}$
    45004125\end{cfa}
    45014126\begin{cfa}[mathescape=off,showspaces=true,aboveskip=0pt,belowskip=0pt]
     
    45064131\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.
    45074132\begin{cfa}[belowskip=0pt]
    4508 sout | 1 | ®nosep® | 2 | 3; §\C{// turn off implicit separator for the next item}§
     4133sout | 1 | ®nosep® | 2 | 3; $\C{// turn off implicit separator for the next item}$
    45094134\end{cfa}
    45104135\begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
     
    45124137\end{cfa}
    45134138\begin{cfa}[belowskip=0pt]
    4514 sout | sepOff | 1 | ®sep® | 2 | 3; §\C{// turn on implicit separator for the next item}§
     4139sout | sepOff | 1 | ®sep® | 2 | 3; $\C{// turn on implicit separator for the next item}$
    45154140\end{cfa}
    45164141\begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
     
    45194144The tuple separator also responses to being turned on and off.
    45204145\begin{cfa}[belowskip=0pt]
    4521 sout | t1 | ®nosep® | t2; §\C{// turn off implicit separator for the next item}§
     4146sout | t1 | ®nosep® | t2; $\C{// turn off implicit separator for the next item}$
    45224147\end{cfa}
    45234148\begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
     
    45274152Use ©sep© to accomplish this functionality.
    45284153\begin{cfa}[belowskip=0pt]
    4529 sout | ®sep® | 1 | 2 | 3 | ®sep®; §\C{// sep does nothing at start/end of line}§
     4154sout | ®sep® | 1 | 2 | 3 | ®sep®; $\C{// sep does nothing at start/end of line}$
    45304155\end{cfa}
    45314156\begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
     
    45334158\end{cfa}
    45344159\begin{cfa}[belowskip=0pt]
    4535 sout | ®sepVal® | 1 | 2 | 3 | ®sepVal® ; §\C{// use sepVal to print separator at start/end of line}§
     4160sout | ®sepVal® | 1 | 2 | 3 | ®sepVal® ; $\C{// use sepVal to print separator at start/end of line}$
    45364161\end{cfa}
    45374162\begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
     
    45724197\Indexc{nl}\index{manipulator!nl@©nl©} inserts a newline.
    45734198\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}§
     4199sout | ®nl®; $\C{// only print newline}$
     4200sout | 2; $\C{// implicit newline}$
     4201sout | 3 | ®nl® | 4 | ®nl®; $\C{// terminating nl merged with implicit newline}$
     4202sout | 5 | ®nl® | ®nl®; $\C{// again terminating nl merged with implicit newline}$
     4203sout | 6; $\C{// implicit newline}$
    45794204
    458042052
     
    50234648®mutex( sout )® {
    50244649        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}$
    50264651        sout | 4;
    50274652} // implicitly release sout lock
     
    50354660        int x, y, z, w;
    50364661        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}$
    50384663        sin | w;
    50394664} // implicitly release sin lock
     
    50444669\Textbf{WARNING:} The general problem of \Index{nested locking} can occur if routines are called in an I/O sequence that block, \eg:
    50454670\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}$
    50474672\end{cfa}
    50484673If 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.
     
    50624687\begin{cfa}
    5063468812®,®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§
     468912®.®345®,®123          $\C{// period separator, comma decimal-point}$
     469012$\Sp$345®,®123®.®     $\C{// space separator, comma decimal-point, period terminator}\CRT$
    50664691\end{cfa}
    50674692A locale is selected with function ©setlocale©, and the corresponding locale package \emph{must} be installed on the underlying system;
     
    50744699\begin{cfa}
    50754700#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}$
    50784703
    50794704int main() {
     
    51474772int main() {
    51484773        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}$
    51514776        int i = 3, j = 5, k = 7;
    51524777        double x = 12345678.9, y = 98765.4321e-11;
    51534778
    51544779        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}$
    51574782        sout | i | hex(j) | wd(10, k) | sci(x) | unit(eng(y)) | "abc";
    51584783
    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}$
    51604785        ®istrstream isstr = { buf2 };®
    51614786        char s[10];
     
    53094934// Subsequent arguments can be specified for initialization
    53104935
    5311 void ?{}( Widget & w ) { §\C{// default constructor}§
     4936void ?{}( Widget & w ) { $\C{// default constructor}$
    53124937        w.id = -1;
    53134938        w.size = 0.0;
     
    53234948
    53244949// ^?{} is the destructor operator identifier
    5325 void ^?{}( Widget & w ) { §\C{// destructor}§
     4950void ^?{}( Widget & w ) { $\C{// destructor}$
    53264951        w.id = 0;
    53274952        w.size = 0.0;
     
    53324957}
    53334958
    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}§
     4959Widget baz; $\C{// reserve space only}$
     4960Widget foo{}; $\C{// calls default constructor}$
     4961Widget bar{ 23, 2.45 }; $\C{// calls constructor with values}$
     4962baz{ 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}$
    53404965\end{cfa}
    53414966\caption{Constructors and Destructors}
     
    58555480
    58565481®coroutine® Fibonacci {
    5857         int fn; §\C{// used for communication}§
     5482        int fn; $\C{// used for communication}$
    58585483};
    58595484
    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}§
     5485void 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}$
    58665491        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}$
    58695494        }
    58705495}
    58715496int next( Fibonacci & fib ) with( fib ) {
    5872         ®resume( fib );® §\C{// restart last suspend}§
     5497        ®resume( fib );® $\C{// restart last suspend}$
    58735498        return fn;
    58745499}
    58755500int main() {
    58765501        Fibonacci f1, f2;
    5877         for ( 10 ) { §\C{// print N Fibonacci values}§
     5502        for ( 10 ) { $\C{// print N Fibonacci values}$
    58785503                sout | next( f1 ) | next( f2 );
    58795504        }
     
    59135538int inc( AtomicCnt & ®mutex® c, int inc = 1 ) with(c) { return counter += inc; }
    59145539int dec( AtomicCnt & ®mutex® c, int dec = 1 ) with(c) { return counter -= dec; }
    5915 forall( ostype & | ostream( ostype ) ) { §\C{// print any stream}§
     5540forall( ostype & | ostream( ostype ) ) { $\C{// print any stream}$
    59165541        ostype & ?|?( ostype & os, AtomicCnt c ) { return os | c.counter; }
    59175542        void ?|?( ostype & os, AtomicCnt c ) { (ostype &)(os | c.counter); ends( os ); }
    59185543}
    59195544
    5920 AtomicCnt global; §\C{// shared}§
     5545AtomicCnt global; $\C{// shared}$
    59215546
    59225547thread MyThread {};
     
    59295554int main() {
    59305555        enum { Threads = 4 };
    5931         processor p[Threads - 1]; §\C{// + starting processor}§
     5556        processor p[Threads - 1]; $\C{// + starting processor}$
    59325557        {
    59335558                MyThread t[Threads];
    59345559        }
    5935         sout | global; §\C{// print 0}§
     5560        sout | global; $\C{// print 0}$
    59365561}
    59375562\end{cfa}
     
    74067031In \CFA, there are ambiguous cases with dereference and operator identifiers, \eg ©int *?*?()©, where the string ©*?*?© can be interpreted as:
    74077032\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}$
    74107035\end{cfa}
    74117036By default, the first interpretation is selected, which does not yield a meaningful parse.
     
    74597084\eg:
    74607085\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 );}§
     7086x; $\C{// int x}$
     7087*y; $\C{// int *y}$
     7088f( p1, p2 ); $\C{// int f( int p1, int p2 );}$
     7089g( p1, p2 ) int p1, p2; $\C{// int g( int p1, int p2 );}$
    74657090\end{cfa}
    74667091\CFA continues to support K\&R routine definitions:
    74677092\begin{cfa}
    7468 f( a, b, c ) §\C{// default int return}§
    7469         int a, b; char c §\C{// K\&R parameter declarations}§
     7093f( a, b, c ) $\C{// default int return}$
     7094        int a, b; char c $\C{// K\&R parameter declarations}$
    74707095{
    74717096        ...
     
    74867111int rtn( int i );
    74877112int rtn( char c );
    7488 rtn( 'x' ); §\C{// programmer expects 2nd rtn to be called}§
     7113rtn( 'x' ); $\C{// programmer expects 2nd rtn to be called}$
    74897114\end{cfa}
    74907115\item[Rationale:] it is more intuitive for the call to ©rtn© to match the second version of definition of ©rtn© rather than the first.
     
    75087133\item[Change:] make string literals ©const©:
    75097134\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}§
     7135char * p = "abc"; $\C{// valid in C, deprecated in \CFA}$
     7136char * q = expr ? "abc" : "de"; $\C{// valid in C, invalid in \CFA}$
    75127137\end{cfa}
    75137138The type of a string literal is changed from ©[] char© to ©const [] char©.
     
    75167141\begin{cfa}
    75177142char * p = "abc";
    7518 p[0] = 'w'; §\C{// segment fault or change constant literal}§
     7143p[0] = 'w'; $\C{// segment fault or change constant literal}$
    75197144\end{cfa}
    75207145The same problem occurs when passing a string literal to a routine that changes its argument.
     
    75287153\item[Change:] remove \newterm{tentative definitions}, which only occurs at file scope:
    75297154\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}§
     7155int i; $\C{// forward definition}$
     7156int *j = ®&i®; $\C{// forward reference, valid in C, invalid in \CFA}$
     7157int i = 0; $\C{// definition}$
    75337158\end{cfa}
    75347159is valid in C, and invalid in \CFA because duplicate overloaded object definitions at the same scope level are disallowed.
     
    75367161\begin{cfa}
    75377162struct 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}§
     7163static struct X a; $\C{// forward definition}$
     7164static struct X b = { 0, ®&a® };$\C{// forward reference, valid in C, invalid in \CFA}$
     7165static struct X a = { 1, &b }; $\C{// definition}$
    75417166\end{cfa}
    75427167\item[Rationale:] avoids having different initialization rules for builtin types and user-defined types.
     
    75537178struct Person {
    75547179        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)}$
    75577182        };
    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}$
    75617186};
    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}$
     7188Person®.Colour® pc = Person®.®R;$\C{// type/enum defined inside}$
     7189Person®.®Face pretty; $\C{// type defined inside}\CRT$
    75657190\end{cfa}
    75667191In 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.
     
    75797204\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:
    75807205\begin{cfa}
    7581 struct Y; §\C{// struct Y and struct X are at the same scope}§
     7206struct Y; $\C{// struct Y and struct X are at the same scope}$
    75827207struct X {
    75837208        struct Y { /* ... */ } y;
     
    75947219\begin{cfa}
    75957220void 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 *}$
    75987223}
    75997224\end{cfa}
     
    78377462Type-safe allocation is provided for all C allocation routines and new \CFA allocation routines, \eg in
    78387463\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}§
     7464int * ip = (int *)malloc( sizeof(int) );                $\C{// C}$
     7465int * ip = malloc();                                                    $\C{// \CFA type-safe version of C malloc}$
     7466int * ip = alloc();                                                             $\C{// \CFA type-safe uniform alloc}$
    78427467\end{cfa}
    78437468the latter two allocations determine the allocation size from the type of ©p© (©int©) and cast the pointer to the allocated storage to ©int *©.
     
    78467471\begin{cfa}
    78477472struct S { int i; } __attribute__(( aligned( 128 ) )); // cache-line alignment
    7848 S * sp = malloc();                                                              §\C{// honour type alignment}§
     7473S * sp = malloc();                                                              $\C{// honour type alignment}$
    78497474\end{cfa}
    78507475the storage allocation is implicitly aligned to 128 rather than the default 16.
     
    78617486\CFA memory management extends allocation to support constructors for initialization of allocated storage, \eg in
    78627487\begin{cfa}
    7863 struct S { int i; };                                                    §\C{// cache-line alignment}§
     7488struct S { int i; };                                                    $\C{// cache-line alignment}$
    78647489void ?{}( S & s, int i ) { s.i = i; }
    78657490// assume ?|? operator for printing an S
    78667491
    7867 S & sp = *®new®( 3 );                                                   §\C{// call constructor after allocation}§
     7492S & sp = *®new®( 3 );                                                   $\C{// call constructor after allocation}$
    78687493sout | sp.i;
    78697494®delete®( &sp );
    78707495
    7871 S * spa = ®anew®( 10, 5 );                                              §\C{// allocate array and initialize each array element}§
     7496S * spa = ®anew®( 10, 5 );                                              $\C{// allocate array and initialize each array element}$
    78727497for ( i; 10 ) sout | spa[i] | nonl;
    78737498sout | nl;
     
    79087533        // $\CFA$ safe general allocation, fill, resize, alignment, array
    79097534        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}$
    79317556
    79327557        // $\CFA$ safe initialization/copy, i.e., implicit size specification
     
    79897614\leavevmode
    79907615\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    7991 forall( T | { int ?<?( T, T ); } ) §\C{// location}§
     7616forall( T | { int ?<?( T, T ); } ) $\C{// location}$
    79927617T * bsearch( T key, const T * arr, size_t dim );$\indexc{bsearch}$
    79937618
    7994 forall( T | { int ?<?( T, T ); } ) §\C{// position}§
     7619forall( T | { int ?<?( T, T ); } ) $\C{// position}$
    79957620unsigned int bsearch( T key, const T * arr, size_t dim );
    79967621
     
    79997624
    80007625forall( 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}$
    80037628        E * bsearchl( E key, const E * vals, size_t dim );$\indexc{bsearchl}$
    80047629        size_t bsearchl( E key, const E * vals, size_t dim );
     
    80477672void srandom( unsigned int seed );$\indexc{srandom}$
    80487673char random( void );$\indexc{random}$
    8049 char random( char u ); §\C{// [0,u)}§
    8050 char random( char l, char u ); §\C{// [l,u]}§
     7674char random( char u ); $\C{// [0,u)}$
     7675char random( char l, char u ); $\C{// [l,u]}$
    80517676int random( void );
    8052 int random( int u ); §\C{// [0,u)}§
    8053 int random( int l, int u ); §\C{// [l,u]}§
     7677int random( int u ); $\C{// [0,u)}$
     7678int random( int l, int u ); $\C{// [l,u]}$
    80547679unsigned 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]}§
     7680unsigned int random( unsigned int u ); $\C{// [0,u)}$
     7681unsigned int random( unsigned int l, unsigned int u ); $\C{// [l,u]}$
    80577682long 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]}§
     7683long int random( long int u ); $\C{// [0,u)}$
     7684long int random( long int l, long int u ); $\C{// [l,u]}$
    80607685unsigned 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}§
     7686unsigned long int random( unsigned long int u ); $\C{// [0,u)}$
     7687unsigned long int random( unsigned long int l, unsigned long int u ); $\C{// [l,u]}$
     7688float random( void );                                            $\C{// [0.0, 1.0)}$
     7689double random( void );                                           $\C{// [0.0, 1.0)}$
     7690float _Complex random( void );                           $\C{// [0.0, 1.0)+[0.0, 1.0)i}$
     7691double _Complex random( void );                          $\C{// [0.0, 1.0)+[0.0, 1.0)i}$
     7692long double _Complex random( void );             $\C{// [0.0, 1.0)+[0.0, 1.0)i}$
    80687693\end{cfa}
    80697694
     
    82647889long double atan2( long double, long double );
    82657890
    8266 float atan( float, float ); §\C{// alternative name for atan2}§
     7891float atan( float, float ); $\C{// alternative name for atan2}$
    82677892double atan( double, double );$\indexc{atan}$
    82687893long double atan( long double, long double );
     
    84918116\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    84928117struct Duration {
    8493         int64_t tn; §\C{// nanoseconds}§
     8118        int64_t tn; $\C{// nanoseconds}$
    84948119};
    84958120
     
    86368261\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    86378262struct Time {
    8638         uint64_t tn; §\C{// nanoseconds since UNIX epoch}§
     8263        uint64_t tn; $\C{// nanoseconds since UNIX epoch}$
    86398264};
    86408265
     
    87018326\leavevmode
    87028327\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    8703 struct Clock { §\C{// virtual clock}§
    8704         Duration offset; §\C{// offset from computer real-time}§
     8328struct Clock { $\C{// virtual clock}$
     8329        Duration offset; $\C{// offset from computer real-time}$
    87058330};
    87068331
    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}§
     8332void ?{}( Clock & clk ); $\C{// create no offset}$
     8333void ?{}( Clock & clk, Duration adj ); $\C{// create with offset}$
     8334void reset( Clock & clk, Duration adj ); $\C{// change offset}$
     8335
     8336Duration resolutionHi(); $\C{// clock resolution in nanoseconds (fine)}$
     8337Duration resolution(); $\C{// clock resolution without nanoseconds (coarse)}$
     8338
     8339Time timeHiRes(); $\C{// real time with nanoseconds}$
     8340Time time(); $\C{// real time without nanoseconds}$
     8341Time time( Clock & clk ); $\C{// real time for given clock}$
     8342Time ?()( Clock & clk ); $\C{//\ \ \ \ alternative syntax}$
     8343timeval time( Clock & clk ); $\C{// convert to C time format}$
    87198344tm 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}§
     8345Duration processor(); $\C{// non-monotonic duration of kernel thread}$
     8346Duration program(); $\C{// non-monotonic duration of program CPU}$
     8347Duration boot(); $\C{// monotonic duration since computer boot}$
    87238348\end{cfa}
    87248349
     
    87618386\begin{cfa}
    87628387struct 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§
     8388void ?{}( PRNG & prng ); $\C{// random seed}$
     8389void ?{}( PRNG & prng, uint32_t seed ); $\C{// fixed seed}$
     8390void set_seed( PRNG & prng, uint32_t seed ); $\C{// set seed}$
     8391uint32_t get_seed( PRNG & prng ); $\C{// get seed}$
     8392uint32_t prng( PRNG & prng ); $\C{// [0,UINT\_MAX]}$
     8393uint32_t prng( PRNG & prng, uint32_t u ); $\C{// [0,u)}$
     8394uint32_t prng( PRNG & prng, uint32_t l, uint32_t u ); $\C{// [l,u]}$
     8395uint32_t calls( PRNG & prng ); $\C{// number of calls}\CRT$
    87718396\end{cfa}
    87728397A ©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.
     
    88228447\begin{cfa}
    88238448void set_seed( uint32_t seed ); $\C[3.75in]{// set global seed}$
    8824 uint32_t get_seed(); §\C{// get global seed}§
     8449uint32_t get_seed(); $\C{// get global seed}$
    88258450// 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]}§
     8451uint32_t prng(); $\C{// [0,UINT\_MAX]}$
     8452uint32_t prng( uint32_t u ); $\C{// [0,u)}$
     8453uint32_t prng( uint32_t l, uint32_t u ); $\C{// [l,u]}$
    88298454// 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§
     8455uint32_t prng( $thread\LstStringStyle{\textdollar}$ & th );     $\C{// [0,UINT\_MAX]}$
     8456uint32_t prng( $thread\LstStringStyle{\textdollar}$ & th, uint32_t u ); $\C{// [0,u)}$
     8457uint32_t prng( $thread\LstStringStyle{\textdollar}$ & th, uint32_t l, uint32_t u );     $\C{// [l,u]}\CRT$
    88338458\end{cfa}
    88348459The only difference between the two sets of ©prng© routines is performance.
     
    89118536
    89128537\begin{cfa}
    8913 void ?{}( Int * this ); §\C{// constructor/destructor}§
     8538void ?{}( Int * this ); $\C{// constructor/destructor}$
    89148539void ?{}( Int * this, Int init );
    89158540void ?{}( Int * this, zero_t );
     
    89208545void ^?{}( Int * this );
    89218546
    8922 Int ?=?( Int * lhs, Int rhs ); §\C{// assignment}§
     8547Int ?=?( Int * lhs, Int rhs ); $\C{// assignment}$
    89238548Int ?=?( Int * lhs, long int rhs );
    89248549Int ?=?( Int * lhs, unsigned long int rhs );
     
    89378562unsigned long int narrow( Int val );
    89388563
    8939 int ?==?( Int oper1, Int oper2 ); §\C{// comparison}§
     8564int ?==?( Int oper1, Int oper2 ); $\C{// comparison}$
    89408565int ?==?( Int oper1, long int oper2 );
    89418566int ?==?( long int oper2, Int oper1 );
     
    89738598int ?>=?( unsigned long int oper1, Int oper2 );
    89748599
    8975 Int +?( Int oper ); §\C{// arithmetic}§
     8600Int +?( Int oper ); $\C{// arithmetic}$
    89768601Int -?( Int oper );
    89778602Int ~?( Int oper );
     
    90558680Int ?>>=?( Int * lhs, mp_bitcnt_t shift );
    90568681
    9057 Int abs( Int oper ); §\C{// number functions}§
     8682Int abs( Int oper ); $\C{// number functions}$
    90588683Int fact( unsigned long int N );
    90598684Int gcd( Int oper1, Int oper2 );
     
    90678692Int sqrt( Int oper );
    90688693
    9069 forall( dtype istype | istream( istype ) ) istype * ?|?( istype * is, Int * mp );  §\C{// I/O}§
     8694forall( dtype istype | istream( istype ) ) istype * ?|?( istype * is, Int * mp );  $\C{// I/O}$
    90708695forall( dtype ostype | ostream( ostype ) ) ostype * ?|?( ostype * os, Int mp );
    90718696\end{cfa}
     
    91668791// implementation
    91678792struct Rational {$\indexc{Rational}$
    9168         long int numerator, denominator; §\C{// invariant: denominator > 0}§
     8793        long int numerator, denominator; $\C{// invariant: denominator > 0}$
    91698794}; // Rational
    91708795
    9171 Rational rational(); §\C{// constructors}§
     8796Rational rational(); $\C{// constructors}$
    91728797Rational rational( long int n );
    91738798Rational rational( long int n, long int d );
     
    91758800void ?{}( Rational * r, one_t );
    91768801
    9177 long int numerator( Rational r ); §\C{// numerator/denominator getter/setter}§
     8802long int numerator( Rational r ); $\C{// numerator/denominator getter/setter}$
    91788803long int numerator( Rational r, long int n );
    91798804long int denominator( Rational r );
    91808805long int denominator( Rational r, long int d );
    91818806
    9182 int ?==?( Rational l, Rational r ); §\C{// comparison}§
     8807int ?==?( Rational l, Rational r ); $\C{// comparison}$
    91838808int ?!=?( Rational l, Rational r );
    91848809int ?<?( Rational l, Rational r );
     
    91878812int ?>=?( Rational l, Rational r );
    91888813
    9189 Rational -?( Rational r ); §\C{// arithmetic}§
     8814Rational -?( Rational r ); $\C{// arithmetic}$
    91908815Rational ?+?( Rational l, Rational r );
    91918816Rational ?-?( Rational l, Rational r );
     
    91938818Rational ?/?( Rational l, Rational r );
    91948819
    9195 double widen( Rational r ); §\C{// conversion}§
     8820double widen( Rational r ); $\C{// conversion}$
    91968821Rational narrow( double f, long int md );
    91978822
  • libcfa/src/Makefile.am

    rf988834 r59c8dff  
    4848        math.trait.hfa \
    4949        math.hfa \
    50         raii.hfa \
    5150        time_t.hfa \
    5251        virtual_dtor.hfa \
  • libcfa/src/collections/array.hfa

    rf988834 r59c8dff  
    131131
    132132    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);
    156142    }
    157143}
     
    161147//
    162148
    163 forall( Te * )
     149forall( Te )
    164150static inline Te mkar_( tag(Te) ) {}
    165151
  • libcfa/src/collections/string.cfa

    rf988834 r59c8dff  
    1010// Created On       : Fri Sep 03 11:00:00 2021
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Jan 14 12:03:47 2024
    13 // Update Count     : 240
     12// Last Modified On : Wed Oct 18 21:52:09 2023
     13// Update Count     : 208
    1414//
    1515
     
    2929// string RAII
    3030
     31
     32void ?{}( string & this ) {
     33    (this.inner) { malloc() };
     34    ?{}( *this.inner );
     35}
     36
    3137// 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;
     38static 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
     43void ?{}( string & this, const string & other ) {
     44    (this.inner) { malloc() };
     45    ?{}( *this.inner, *other.inner, COPY_VALUE );
     46}
     47
     48void ?{}( string & this, string & other ) {
     49    ?{}( this, (const string &) other );
     50}
     51
     52void ?{}( string & this, const char * val ) {
     53    (this.inner) { malloc() };
     54    ?{}( *this.inner, val );
     55}
     56
     57void ?{}( string & this, const char * buffer, size_t bsize) {
     58    (this.inner) { malloc() };
     59    ?{}( *this.inner, buffer, bsize );
     60}
     61
     62void ^?{}( string & this ) {
     63    ^(*this.inner){};
     64    free( this.inner );
     65    this.inner = 0p;
    7666}
    7767
     
    7969// Alternate construction: request shared edits
    8070
    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);
     71string_WithSharedEdits ?`shareEdits( string & this ) {
     72    string_WithSharedEdits ret = { &this };
     73    return ret;
     74}
     75
     76void ?{}( string & this, string_WithSharedEdits src ) {
     77    ?{}( this, *src.s->inner, 0, src.s->inner->Handle.lnth);
    8878}
    8979
     
    9181// Assignment
    9282
    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);
     83void ?=?( string & this, const char * val ) {
     84    (*this.inner) = val;
     85}
     86
     87void ?=?(string & this, const string & other) {
     88    (*this.inner) = (*other.inner);
     89}
     90
     91void ?=?( string & this, char val ) {
     92    (*this.inner) = val;
     93}
     94
     95string & ?=?(string & this, string & other) { //// <---- straw man change
     96    (*this.inner) = (*other.inner);
     97    return this;
    11598}
    11699
     
    119102// Input-Output
    120103
    121 ofstream & ?|?( ofstream & out, const string & s ) {
    122     return out | (*s.inner); // print internal string_res
    123 }
    124 
    125 void ?|?( ofstream & out, const string & s ) {
    126     (ofstream &)(out | (*s.inner)); ends( out );
     104ofstream & ?|?( ofstream & out, const string & this ) {
     105    return out | (*this.inner); // print internal string_res
     106}
     107
     108void ?|?( ofstream & out, const string & this ) {
     109    (ofstream &)(out | (*this.inner)); ends( out );
    127110}
    128111
     
    141124}
    142125
    143 ifstream & ?|?(ifstream & in, string & s) {
    144     return in | (*s.inner); // read to internal string_res
    145 }
    146 
    147 void ?|?( ifstream & in, string & s ) {
    148     in | (*s.inner);
     126ifstream & ?|?(ifstream & in, string & this) {
     127    return in | (*this.inner); // read to internal string_res
     128}
     129
     130void ?|?( ifstream & in, string & this ) {
     131    in | (*this.inner);
    149132}
    150133
     
    161144// Slicing
    162145
    163 string ?()( string & s, size_t start, size_t len ) {
    164     string ret = { *s.inner, start, len };
     146string ?()( string & this, size_t start, size_t end ) {
     147    string ret = { *this.inner, start, end };
    165148    return ret`shareEdits;
    166149}
    167150
    168 string ?()( string & s, size_t start ) {
    169     string ret = { *s.inner, start, size( s ) - start };
     151string ?()( string & this, size_t start ) {
     152    string ret = { *this.inner, start, size( this ) };
    170153    return ret`shareEdits;
    171154}
     
    174157// Comparison
    175158
    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; }
     159int  cmp (const string &s1, const string &s2) { return cmp(*s1.inner , *s2.inner); }
     160bool ?==?(const string &s1, const string &s2) { return     *s1.inner == *s2.inner ; }
     161bool ?!=?(const string &s1, const string &s2) { return     *s1.inner != *s2.inner ; }
     162bool ?>? (const string &s1, const string &s2) { return     *s1.inner >  *s2.inner ; }
     163bool ?>=?(const string &s1, const string &s2) { return     *s1.inner >= *s2.inner ; }
     164bool ?<=?(const string &s1, const string &s2) { return     *s1.inner <= *s2.inner ; }
     165bool ?<? (const string &s1, const string &s2) { return     *s1.inner <  *s2.inner ; }
     166
     167int  cmp (const string &s1, const char*   s2) { return cmp(*s1.inner ,   s2      ); }
     168bool ?==?(const string &s1, const char*   s2) { return     *s1.inner ==  s2       ; }
     169bool ?!=?(const string &s1, const char*   s2) { return     *s1.inner !=  s2       ; }
     170bool ?>? (const string &s1, const char*   s2) { return     *s1.inner >   s2       ; }
     171bool ?>=?(const string &s1, const char*   s2) { return     *s1.inner >=  s2       ; }
     172bool ?<=?(const string &s1, const char*   s2) { return     *s1.inner <=  s2       ; }
     173bool ?<? (const string &s1, const char*   s2) { return     *s1.inner <   s2       ; }
     174
     175int  cmp (const char*   s1, const string &s2) { return cmp( s1       , *s2.inner); }
     176bool ?==?(const char*   s1, const string &s2) { return      s1       == *s2.inner ; }
     177bool ?!=?(const char*   s1, const string &s2) { return      s1       != *s2.inner ; }
     178bool ?>? (const char*   s1, const string &s2) { return      s1       >  *s2.inner ; }
     179bool ?>=?(const char*   s1, const string &s2) { return      s1       >= *s2.inner ; }
     180bool ?<=?(const char*   s1, const string &s2) { return      s1       <= *s2.inner ; }
     181bool ?<? (const char*   s1, const string &s2) { return      s1       <  *s2.inner ; }
    199182
    200183
     
    203186
    204187size_t size(const string & s) {
    205     return size( *s.inner );
     188    return size( * s.inner );
    206189}
    207190
     
    209192// Concatenation
    210193
    211 void ?+=?(string & s, char c) {
    212     (*s.inner) += c;
     194void ?+=?(string & s, char other) {
     195    (*s.inner) += other;
    213196}
    214197
     
    217200}
    218201
    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) {
     202void ?+=?(string & s, const char * other) {
     203    (*s.inner) += other;
     204}
     205
     206string ?+?(const string & s, char other) {
    232207    string ret = s;
    233     ret += c;
     208    ret += other;
    234209    return ret;
    235210}
     
    247222}
    248223
    249 string ?+?(const string & s, const char * c) {
     224string ?+?(const string & s, const char * other) {
    250225    string ret = s;
    251     ret += c;
     226    ret += other;
    252227    return ret;
    253228}
     
    256231// Repetition
    257232
    258 void ?*=?(string & s, size_t factor) {
    259     (*s.inner) *= factor;
    260 }
    261 
    262233string ?*?(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
     239string ?*?(char c, size_t size) {
     240    string ret = "";
     241    for ((size_t)size) ret += c;
     242    return ret;
     243}
     244
     245string ?*?(const char *s, size_t factor) {
     246    string ss = s;
     247    return ss * factor;
    278248}
    279249
     
    286256
    287257string ?[?](string & s, size_t index) {
    288     string ret = { *s.inner, index, 1 };
     258    string ret = { *s.inner, index, index + 1 };
    289259    return ret`shareEdits;
    290260}
     
    369339// charclass, include, exclude
    370340
    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;
     341void ?{}( charclass & this, const string & chars) {
     342    (this.inner) { malloc() };
     343    ?{}( *this.inner, *(const string_res *)chars.inner );
     344}
     345
     346void ?{}( charclass & this, const char * chars ) {
     347    (this.inner) { malloc() };
     348    ?{}( *this.inner, chars );
     349}
     350
     351void ?{}( charclass & this, const char * chars, size_t charssize ) {
     352    (this.inner) { malloc() };
     353    ?{}( *this.inner, chars, charssize );
     354}
     355
     356void ^?{}( charclass & this ) {
     357    ^(*this.inner){};
     358    free( this.inner );
     359    this.inner = 0p;
    390360}
    391361
  • libcfa/src/collections/string.hfa

    rf988834 r59c8dff  
    1010// Created On       : Fri Sep 03 11:00:00 2021
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Jan 14 12:03:46 2024
    13 // Update Count     : 81
     12// Last Modified On : Sat Sep  2 11:26:28 2023
     13// Update Count     : 55
    1414//
    1515
     
    2929// Getters
    3030size_t size(const string & s);
    31 static inline size_t strlen(const string & s) { return size( s ); }
    3231
    3332// RAII, assignment
    34 void ?{}(string & s); // empty string
     33void ?{}(string & this); // empty string
     34void ?{}(string & s, const char * initial); // copy from string literal (NULL-terminated)
     35void ?{}(string & s, const char * buffer, size_t bsize); // copy specific length from buffer
     36
    3537void ?{}(string & s, const string & s2);
    36 void ?{}(string & s, const string & s2, size_t maxlen);
    3738void ?{}(string & s, string & s2);
    3839
    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);
     40void ?=?(string & s, const char * other); // copy assignment from literal
     41void ?=?(string & s, const string & other);
     42void ?=?(string & s, char other);
     43string & ?=?(string & s, string & other);  // surprising ret seems to help avoid calls to autogen
    4944//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 
    5645void ^?{}(string & s);
    5746
     
    6049    string * s;
    6150};
    62 string_WithSharedEdits ?`shareEdits( string & s );
    63 void ?{}( string & s, string_WithSharedEdits src );
     51string_WithSharedEdits ?`shareEdits( string & this );
     52void ?{}( string & this, string_WithSharedEdits src );
    6453
    6554// IO Operator
     
    6756void ?|?(ofstream & out, const string & s);
    6857ifstream & ?|?(ifstream & in, string & s);
    69 void ?|?( ifstream & in, string & s );
     58void ?|?( ifstream & in, string & this );
    7059
    7160static inline {
     
    9281        _Istream_Sstr wdi( unsigned int rwd, string & s ) { return (_Istream_Sstr)@{ s, {{0p}, rwd, {.flags.rwd : true}} }; }
    9382        _Istream_Sstr getline( string & s, const char delimiter = '\n' ) {
    94                 return (_Istream_Sstr)@{ s, {{.delimiters : { delimiter, '\0' } }, -1, {.flags.delimiter : true, .flags.inex : true}} };
     83                return (_Istream_Sstr)@{ s, {{.delimiter : { delimiter, '\0' } }, -1, {.flags.delimiter : true, .flags.inex : true}} };
    9584        }
    9685        _Istream_Sstr & getline( _Istream_Sstr & fmt, const char delimiter = '\n' ) {
    97                 fmt.delimiters[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;
    9887        }
    9988        _Istream_Sstr incl( const char scanset[], string & s ) { return (_Istream_Sstr)@{ s, {{scanset}, -1, {.flags.inex : false}} }; }
     
    10897
    10998// Concatenation
    110 void ?+=?(string & s, char c); // append a character
     99void ?+=?(string & s, char other); // append a character
    111100void ?+=?(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
     101void ?+=?(string & s, const char * other); // append-concatenate to first string
     102string ?+?(const string & s, char other); // add a character to a copy of the string
    117103string ?+?(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; }
     104string ?+?(const char * s1, const char * s2); // concatenate both strings
     105string ?+?(const string & s, const char * other); // copy and concatenate with NULL-terminated string
    125106
    126107// Repetition
    127108string ?*?(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);
     109string ?*?(char c, size_t size);
     110string ?*?(const char *s, size_t size);
    131111
    132112// Character access
     
    136116
    137117// Comparisons
    138 int  strcmp (const string &, const string &);
     118int  cmp (const string &, const string &);
    139119bool ?==?(const string &, const string &);
    140120bool ?!=?(const string &, const string &);
     
    144124bool ?<? (const string &, const string &);
    145125
    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 *, const string &);
    156 bool ?!=?(const char *, const string &);
    157 bool ?>? (const char *, const string &);
    158 bool ?>=?(const char *, const string &);
    159 bool ?<=?(const char *, const string &);
    160 bool ?<? (const char *, const string &);
     126int  cmp (const string &, const char*);
     127bool ?==?(const string &, const char*);
     128bool ?!=?(const string &, const char*);
     129bool ?>? (const string &, const char*);
     130bool ?>=?(const string &, const char*);
     131bool ?<=?(const string &, const char*);
     132bool ?<? (const string &, const char*);
     133
     134int  cmp (const char*, const string &);
     135bool ?==?(const char*, const string &);
     136bool ?!=?(const char*, const string &);
     137bool ?>? (const char*, const string &);
     138bool ?>=?(const char*, const string &);
     139bool ?<=?(const char*, const string &);
     140bool ?<? (const char*, const string &);
    161141
    162142
    163143// Slicing
    164 string ?()( string & s, size_t start, size_t len );  // TODO const?
    165 string ?()( string & s, size_t start);
     144string ?()( string & this, size_t start, size_t end );  // TODO const?
     145string ?()( string & this, size_t start);
    166146
    167147// String search
     
    197177
    198178
     179
    199180struct charclass {
    200181    charclass_res * inner;
  • libcfa/src/collections/string_res.cfa

    rf988834 r59c8dff  
    1010// Created On       : Fri Sep 03 11:00:00 2021
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Jan 16 22:19:27 2024
    13 // Update Count     : 35
     12// Last Modified On : Wed Oct 18 21:54:54 2023
     13// Update Count     : 15
    1414//
    1515
     
    2222// Workaround is:  EndVbyte = TEMP_ALLOC(char, CurrSize)
    2323// Should be:      EndVbyte = alloc(CurrSize)
    24 #define TEMP_ALLOC(T, n) (( T * ) malloc( n * sizeof( T ) ))
     24#define TEMP_ALLOC(T, n) (( T* ) malloc( n * sizeof( T ) ))
    2525
    2626#include <assert.h>
     
    3333
    3434struct 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
    3839   
    39     int InitSize;                                                               // initial number of bytes in the byte-string area
    40     int CurrSize;                                                               // current number of bytes in the byte-string area
    41     char *StartVbyte;                                                   // pointer to the `st byte of the start of the byte-string area
    42     char *EndVbyte;                                                             // pointer to the next byte after the end of the currently used portion of byte-string area
    43     void *ExtVbyte;                                                             // pointer to the next byte after the end of the byte-string area
    44 
    45     HandleNode Header;                                                  // header node for handle list
     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
    4647}; // VbyteHeap
    4748
    4849   
    49 static void compaction( VbyteHeap & );                  // compaction of the byte area
    50 static void garbage( VbyteHeap &, int );                // garbage collect the byte area
     50static void compaction( VbyteHeap & );                          // compaction of the byte area
     51static void garbage( VbyteHeap &, int );                                // garbage collect the byte area
    5152static void extend( VbyteHeap &, int );                 // extend the size of the byte area
    5253static void reduce( VbyteHeap &, int );                 // reduce the size of the byte area
     
    6667// Allocate the storage for the variable sized area and intialize the heap variables.
    6768
    68 static void ?{}( VbyteHeap & s, size_t Size ) with(s) {
    69 #ifdef VbyteDebug
    70     serr | "enter:VbyteHeap::VbyteHeap, s:" | &s | " Size:" | Size;
     69static void ?{}( VbyteHeap & this, size_t Size ) with(this) {
     70#ifdef VbyteDebug
     71    serr | "enter:VbyteHeap::VbyteHeap, this:" | &this | " Size:" | Size;
    7172#endif // VbyteDebug
    7273    NoOfCompactions = NoOfExtensions = NoOfReductions = 0;
     
    7576    ExtVbyte = (void *)( StartVbyte + CurrSize );
    7677    Header.flink = Header.blink = &Header;
    77     Header.ulink = &s;
     78    Header.ulink = & this;
    7879#ifdef VbyteDebug
    7980    HeaderPtr = &Header;
    80     serr | "exit:VbyteHeap::VbyteHeap, s:" | &s;
     81    serr | "exit:VbyteHeap::VbyteHeap, this:" | &this;
    8182#endif // VbyteDebug
    8283} // VbyteHeap
     
    8586// Release the dynamically allocated storage for the byte area.
    8687
    87 static void ^?{}( VbyteHeap & s ) with(s) {
     88static void ^?{}( VbyteHeap & this ) with(this) {
    8889    free( StartVbyte );
    8990} // ~VbyteHeap
     
    9697// creator.
    9798
    98 static void ?{}( HandleNode & s ) with(s) {
    99 #ifdef VbyteDebug
    100     serr | "enter:HandleNode::HandleNode, s:" | &s;
     99static void ?{}( HandleNode & this ) with(this) {
     100#ifdef VbyteDebug
     101    serr | "enter:HandleNode::HandleNode, this:" | &this;
    101102#endif // VbyteDebug
    102103    s = 0;
    103104    lnth = 0;
    104105#ifdef VbyteDebug
    105     serr | "exit:HandleNode::HandleNode, s:" | &s;
     106    serr | "exit:HandleNode::HandleNode, this:" | &this;
    106107#endif // VbyteDebug
    107108} // HandleNode
     
    111112// collection.
    112113
    113 static void ?{}( HandleNode & s, VbyteHeap & vh ) with(s) {
    114 #ifdef VbyteDebug
    115     serr | "enter:HandleNode::HandleNode, s:" | &s;
     114static void ?{}( HandleNode & this, VbyteHeap & vh ) with(this) {
     115#ifdef VbyteDebug
     116    serr | "enter:HandleNode::HandleNode, this:" | &this;
    116117#endif // VbyteDebug
    117118    s = 0;
    118119    lnth = 0;
    119120    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;
    123124#endif // VbyteDebug
    124125} // HandleNode
     
    128129// is the responsibility of the creator to destroy it.
    129130
    130 static void ^?{}( HandleNode & s ) with(s) {
    131 #ifdef VbyteDebug
    132     serr | "enter:HandleNode::~HandleNode, s:" | & s;
     131static void ^?{}( HandleNode & this ) with(this) {
     132#ifdef VbyteDebug
     133    serr | "enter:HandleNode::~HandleNode, this:" | & this;
    133134    {
    134135        serr | nlOff;
     
    141142    }
    142143#endif // VbyteDebug
    143     DeleteNode( s );
     144    DeleteNode( this );
    144145} // ~HandleNode
    145146
     
    150151static string_sharectx default_string_sharectx = {NEW_SHARING}; // stable bottom of stack
    151152
    152 void ?{}( string_sharectx & s, StringSharectx_Mode mode ) with( s ) {
     153void ?{}( string_sharectx & this, StringSharectx_Mode mode ) with( this ) {
    153154    (older){ ambient_string_sharectx };
    154155    if ( mode == NEW_SHARING ) {
     
    158159        (activeHeap){ 0p };
    159160    }
    160     ambient_string_sharectx = & s;
    161 }
    162 
    163 void ^?{}( string_sharectx & s ) with( s ) {
     161    ambient_string_sharectx = & this;
     162}
     163
     164void ^?{}( string_sharectx & this ) with( this ) {
    164165    if ( activeHeap ) delete( activeHeap );
    165166
    166     // unlink s from older-list starting from ambient_string_sharectx
    167     // usually, s==ambient_string_sharectx and the loop runs zero times
     167    // unlink this from older-list starting from ambient_string_sharectx
     168    // usually, this==ambient_string_sharectx and the loop runs zero times
    168169    string_sharectx *& c = ambient_string_sharectx;
    169     while ( c != &s ) &c = &c->older;              // find s
    170     c = s.older;                                   // unlink
     170    while ( c != &this ) &c = &c->older;              // find this
     171    c = this.older;                                   // unlink
    171172}
    172173
     
    180181
    181182size_t DEBUG_string_bytes_avail_until_gc( VbyteHeap * heap ) {
    182     return ((char *)heap->ExtVbyte) - heap->EndVbyte;
     183    return ((char*)heap->ExtVbyte) - heap->EndVbyte;
    183184}
    184185
     
    192193
    193194// Returns the size of the string in bytes
    194 size_t size(const string_res & s) with(s) {
     195size_t size(const string_res &s) with(s) {
    195196    return Handle.lnth;
    196197}
    197198
    198199// Output operator
    199 ofstream & ?|?(ofstream & out, const string_res & s) {
     200ofstream & ?|?(ofstream &out, const string_res &s) {
    200201        // CFA string is NOT null terminated, so print exactly lnth characters in a minimum width of 0.
    201202        out | wd( 0, s.Handle.lnth, s.Handle.s ) | nonl;
     
    203204}
    204205
    205 void ?|?(ofstream & out, const string_res & s) {
     206void ?|?(ofstream &out, const string_res &s) {
    206207        (ofstream &)(out | s); ends( out );
    207208}
    208209
    209210// Input operator
    210 ifstream & ?|?(ifstream & in, string_res & s) {
     211ifstream & ?|?(ifstream &in, string_res &s) {
     212
    211213    // Reading into a temp before assigning to s is near zero overhead in typical cases because of sharing.
    212214    // If s is a substring of something larger, simple assignment takes care of that case correctly.
     
    229231
    230232        // rest of heap is available to read into
    231         int lenReadable = (char *)temp.Handle.ulink->ExtVbyte - temp.Handle.ulink->EndVbyte;
     233        int lenReadable = (char*)temp.Handle.ulink->ExtVbyte - temp.Handle.ulink->EndVbyte;
    232234        assert (lenReadable >= 2);
    233235
     
    236238                        *(temp.Handle.ulink->EndVbyte) = '\0';   // pre-assign empty cstring
    237239            in | wdi( lenReadable, temp.Handle.ulink->EndVbyte );
    238         } catch (cstring_length *) {
     240        } catch (cstring_length*) {
    239241            cont = true;
    240242        }
     
    250252}
    251253
    252 void ?|?( ifstream & in, string_res & s ) {
    253     (ifstream &)(in | s);
     254void ?|?( ifstream & in, string_res & this ) {
     255    (ifstream &)(in | this);
    254256}
    255257
     
    272274                cont = true;
    273275        } 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
    277278                        *(f.s) = cstr;
    278279                }
     
    286287                        cont = true;                                                            // continue not allowed
    287288                } finally {
    288                         if ( ! cf.flags.ignore && cstr[0] != '\0' ) { // something was read
     289                        if ( ! cf.flags.ignore &&
     290                                        cstr[0] != '\0' ) {                                     // something was read
    289291                                *(f.s) += cstr;                                                 // build string chunk at a time
    290292                        }
     
    300302
    301303// Empty constructor
    302 void ?{}(string_res & s) with(s) {
     304void ?{}(string_res &s) with(s) {
    303305    if( ambient_string_sharectx->activeHeap ) {
    304306        (Handle){ * ambient_string_sharectx->activeHeap };
     
    315317}
    316318
    317 static void eagerCopyCtorHelper(string_res & s, const char * rhs, size_t rhslnth) with(s) {
     319static void eagerCopyCtorHelper(string_res &s, const char* rhs, size_t rhslnth) with(s) {
    318320    if( ambient_string_sharectx->activeHeap ) {
    319321        (Handle){ * ambient_string_sharectx->activeHeap };
     
    331333
    332334// Constructor from a raw buffer and size
    333 void ?{}(string_res & s, const char * rhs, size_t rhslnth) with(s) {
     335void ?{}(string_res &s, const char* rhs, size_t rhslnth) with(s) {
    334336    eagerCopyCtorHelper(s, rhs, rhslnth);
    335337}
    336338
    337339// 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) {
     340void ?{}( string_res &s, VbyteHeap & heap, const char* rhs, size_t rhslnth ) with(s) {
    339341    (Handle){ heap };
    340342    Handle.s = VbyteAlloc(*Handle.ulink, rhslnth);
     
    346348}
    347349
    348 
    349350// 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;
     351void ?{}(string_res &s, const string_res & s2, StrResInitMode mode, size_t start, size_t end ) {
     352
    353353    verify( start <= end && end <= s2.Handle.lnth );
    354354
     
    394394}
    395395
    396 static void assignEditSet(string_res & s, string_res * shareEditSetStartPeer, string_res * shareEditSetEndPeer,
     396static void assignEditSet(string_res & this, string_res * shareEditSetStartPeer, string_res * shareEditSetEndPeer,
    397397    char * resultSesStart,
    398398    size_t resultSesLnth,
     
    400400
    401401    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;
    405405    size_t afterLen = shareEditSetEndPeer->Handle.s + shareEditSetEndPeer->Handle.lnth - afterBegin;
    406406
    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;
    411411    if (resultPadPosition)
    412         MoveThisAfter( s.Handle, *resultPadPosition );
     412        MoveThisAfter( this.Handle, *resultPadPosition );
    413413
    414414    // adjust all substring string and handle locations, and check if any substring strings are outside the new base string
    415415    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 ) {
    417417        verify (p->Handle.s >= beforeBegin);
    418418        if ( p->Handle.s >= afterBegin ) {
     
    439439                // take end as end-anchored
    440440                // stretch-shrink p according to the edit
    441                 p->Handle.lnth += s.Handle.lnth;
     441                p->Handle.lnth += this.Handle.lnth;
    442442                p->Handle.lnth -= oldLnth;
    443443            }
     
    452452                // p ends during the edit; p does not include the last character replaced
    453453                // set p to empty string at start of edit
    454                 p->Handle.s = s.Handle.s;
     454                p->Handle.s = this.Handle.s;
    455455                p->Handle.lnth = 0;
    456456            } else {
     
    458458                // clip start of p to start at end of edit
    459459                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;
    461461                p->Handle.lnth -= charsToClip;
    462462            }
     
    467467}
    468468
    469 // traverse the share-edit set (SES) to recover the range of a base string to which `s` belongs
    470 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
     470static 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) {
    474474        if ( editPeer->Handle.s < shareEditSetStartPeer->Handle.s ) {
    475475            shareEditSetStartPeer = editPeer;
     
    481481}
    482482
    483 static string_res & assign_(string_res & s, const char * buffer, size_t bsize, const string_res & valSrc) {
     483static string_res & assign_(string_res &this, const char* buffer, size_t bsize, const string_res & valSrc) {
    484484
    485485    string_res * shareEditSetStartPeer;
    486486    string_res * shareEditSetEndPeer;
    487     locateInShareEditSet( s, shareEditSetStartPeer, shareEditSetEndPeer );
     487    locateInShareEditSet( this, shareEditSetStartPeer, shareEditSetEndPeer );
    488488
    489489    verify( shareEditSetEndPeer->Handle.s >= shareEditSetStartPeer->Handle.s );
    490490    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 context
     491    verify( origEditSetLength >= this.Handle.lnth );
     492
     493    if ( this.shareEditSet_owns_ulink ) {                 // assigning to private context
    494494        // ok to overwrite old value within LHS
    495495        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;
    498498        int suffixLen = shareEditSetEndPeer->Handle.s + shareEditSetEndPeer->Handle.lnth - suffixStartOrig;
    499499
    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 ) ) {
    502502            // growing: copy from old to new
    503             char * dest = VbyteAlloc( *s.Handle.ulink, origEditSetLength + delta );
     503            char * dest = VbyteAlloc( *this.Handle.ulink, origEditSetLength + delta );
    504504            char *destCursor = dest;  memcpy(destCursor, prefixStartOrig, prefixLen);
    505505            destCursor += prefixLen;  memcpy(destCursor, buffer         , bsize    );
    506506            destCursor += bsize;      memcpy(destCursor, suffixStartOrig, suffixLen);
    507             assignEditSet(s, shareEditSetStartPeer, shareEditSetEndPeer,
     507            assignEditSet(this, shareEditSetStartPeer, shareEditSetEndPeer,
    508508                dest,
    509509                origEditSetLength + delta,
     
    513513            // room is already allocated in-place: bubble suffix and overwite middle
    514514            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,
    518518                shareEditSetStartPeer->Handle.s,
    519519                origEditSetLength + delta,
     
    522522
    523523    } else if (                                           // assigning to shared context
    524         s.Handle.lnth == origEditSetLength &&          // overwriting entire run of SES
     524        this.Handle.lnth == origEditSetLength &&          // overwriting entire run of SES
    525525        & valSrc &&                                       // sourcing from a managed string
    526         valSrc.Handle.ulink == s.Handle.ulink  ) {     // sourcing from same heap
     526        valSrc.Handle.ulink == this.Handle.ulink  ) {     // sourcing from same heap
    527527
    528528        // SES's result will only use characters from the source string => reuse source
    529         assignEditSet(s, shareEditSetStartPeer, shareEditSetEndPeer,
     529        assignEditSet(this, shareEditSetStartPeer, shareEditSetEndPeer,
    530530            valSrc.Handle.s,
    531531            valSrc.Handle.lnth,
     
    537537
    538538        // full string is from start of shareEditSetStartPeer thru end of shareEditSetEndPeer
    539         // `s` occurs in the middle of it, to be replaced
     539        // `this` occurs in the middle of it, to be replaced
    540540        // build up the new text in `pasting`
    541541
    542542        string_res pasting = {
    543             * s.Handle.ulink,                               // maintain same heap, regardless of context
     543            * this.Handle.ulink,                               // maintain same heap, regardless of context
    544544            shareEditSetStartPeer->Handle.s,                   // start of SES
    545             s.Handle.s - shareEditSetStartPeer->Handle.s }; // length of SES, before s
     545            this.Handle.s - shareEditSetStartPeer->Handle.s }; // length of SES, before this
    546546        append( pasting,
    547             buffer,                                            // start of replacement for s
    548             bsize );                                           // length of replacement for s
     547            buffer,                                            // start of replacement for this
     548            bsize );                                           // length of replacement for this
    549549        append( pasting,
    550             s.Handle.s + s.Handle.lnth,                  // start of SES after s
     550            this.Handle.s + this.Handle.lnth,                  // start of SES after this
    551551            shareEditSetEndPeer->Handle.s + shareEditSetEndPeer->Handle.lnth -
    552             (s.Handle.s + s.Handle.lnth) );              // length of SES, after s
     552            (this.Handle.s + this.Handle.lnth) );              // length of SES, after this
    553553
    554554        // The above string building can trigger compaction.
    555555        // 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,
    559559            pasting.Handle.s,
    560560            pasting.Handle.lnth,
     
    562562    }
    563563
    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
     567string_res & assign(string_res &this, const char* buffer, size_t bsize) {
     568    return assign_(this, buffer, bsize, *0p);
     569}
     570
     571string_res & ?=?(string_res &s, char other) {
     572    return assign(s, &other, 1);
    577573}
    578574
    579575// 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 ) {
     576string_res & ?=?(string_res & this, const string_res & rhs) with( this ) {
     577    return assign_(this, rhs.Handle.s, rhs.Handle.lnth, rhs);
     578}
     579
     580string_res & ?=?(string_res & this, string_res & rhs) with( this ) {
    585581    const string_res & rhs2 = rhs;
    586     return s = rhs2;
     582    return this = rhs2;
    587583}
    588584
    589585
    590586// Destructor
    591 void ^?{}(string_res & s) with(s) {
     587void ^?{}(string_res &s) with(s) {
    592588    // much delegated to implied ^VbyteSM
    593589
     
    607603// With unicode support, this may be different from just the byte at the given
    608604// offset from the start of the string.
    609 char ?[?](const string_res & s, size_t index) with(s) {
     605char ?[?](const string_res &s, size_t index) with(s) {
    610606    //TODO: Check if index is valid (no exceptions yet)
    611607    return Handle.s[index];
    612608}
    613609
    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 };
     610void assignAt(const string_res &s, size_t index, char val) {
     611    string_res editZone = { s, SHARE_EDITS, index, index+1 };
    619612    assign(editZone, &val, 1);
    620613}
     
    624617// Concatenation
    625618
    626 void append(string_res & str1, const char * buffer, size_t bsize) {
     619void append(string_res &str1, const char * buffer, size_t bsize) {
    627620    size_t clnth = str1.Handle.lnth + bsize;
    628621    if ( str1.Handle.s + str1.Handle.lnth == buffer ) { // already juxtapose ?
     
    642635}
    643636
    644 void ?+=?(string_res & str1, const string_res & str2) {
     637void ?+=?(string_res &str1, const string_res &str2) {
    645638    append( str1, str2.Handle.s, str2.Handle.lnth );
    646639}
    647640
    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 }
     641void ?+=?(string_res &s, char other) {
     642    append( s, &other, 1 );
     643}
     644
     645
     646
     647
    667648
    668649//////////////////////////////////////////////////////////
    669650// Comparisons
    670651
    671 int strcmp(const string_res & s1, const string_res & s2) {
     652int cmp(const string_res &s1, const string_res &s2) {
    672653    // return 0;
    673654    int ans1 = memcmp(s1.Handle.s, s2.Handle.s, min(s1.Handle.lnth, s2.Handle.lnth));
     
    676657}
    677658
    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) {
     659bool ?==?(const string_res &s1, const string_res &s2) { return cmp(s1, s2) == 0; }
     660bool ?!=?(const string_res &s1, const string_res &s2) { return cmp(s1, s2) != 0; }
     661bool ?>? (const string_res &s1, const string_res &s2) { return cmp(s1, s2) >  0; }
     662bool ?>=?(const string_res &s1, const string_res &s2) { return cmp(s1, s2) >= 0; }
     663bool ?<=?(const string_res &s1, const string_res &s2) { return cmp(s1, s2) <= 0; }
     664bool ?<? (const string_res &s1, const string_res &s2) { return cmp(s1, s2) <  0; }
     665
     666int cmp (const string_res &s1, const char* s2) {
    686667    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
     671bool ?==?(const string_res &s1, const char* s2) { return cmp(s1, s2) == 0; }
     672bool ?!=?(const string_res &s1, const char* s2) { return cmp(s1, s2) != 0; }
     673bool ?>? (const string_res &s1, const char* s2) { return cmp(s1, s2) >  0; }
     674bool ?>=?(const string_res &s1, const char* s2) { return cmp(s1, s2) >= 0; }
     675bool ?<=?(const string_res &s1, const char* s2) { return cmp(s1, s2) <= 0; }
     676bool ?<? (const string_res &s1, const char* s2) { return cmp(s1, s2) <  0; }
     677
     678int cmp (const char* s1, const string_res & s2) {
    698679    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
     683bool ?==?(const char* s1, const string_res &s2) { return cmp(s1, s2) == 0; }
     684bool ?!=?(const char* s1, const string_res &s2) { return cmp(s1, s2) != 0; }
     685bool ?>? (const char* s1, const string_res &s2) { return cmp(s1, s2) >  0; }
     686bool ?>=?(const char* s1, const string_res &s2) { return cmp(s1, s2) >= 0; }
     687bool ?<=?(const char* s1, const string_res &s2) { return cmp(s1, s2) <= 0; }
     688bool ?<? (const char* s1, const string_res &s2) { return cmp(s1, s2) <  0; }
    708689
    709690
     
    712693// Search
    713694
    714 bool contains(const string_res & s, char ch) {
     695bool contains(const string_res &s, char ch) {
    715696    for ( i; size(s) ) {
    716697        if (s[i] == ch) return true;
     
    719700}
    720701
    721 int find(const string_res & s, char search) {
     702int find(const string_res &s, char search) {
    722703    return findFrom(s, 0, search);
    723704}
    724705
    725 int findFrom(const string_res & s, size_t fromPos, char search) {
     706int findFrom(const string_res &s, size_t fromPos, char search) {
    726707    // FIXME: This paricular overload (find of single char) is optimized to use memchr.
    727708    // The general overload (find of string, memchr applying to its first character) and `contains` should be adjusted to match.
     
    734715}
    735716
    736 int find(const string_res & s, const string_res & search) {
     717int find(const string_res &s, const string_res &search) {
    737718    return findFrom(s, 0, search);
    738719}
    739720
    740 int findFrom(const string_res & s, size_t fromPos, const string_res & search) {
     721int findFrom(const string_res &s, size_t fromPos, const string_res &search) {
    741722    return findFrom(s, fromPos, search.Handle.s, search.Handle.lnth);
    742723}
    743724
    744 int find(const string_res & s, const char * search) {
     725int find(const string_res &s, const char* search) {
    745726    return findFrom(s, 0, search);
    746727}
    747 int findFrom(const string_res & s, size_t fromPos, const char * search) {
     728int findFrom(const string_res &s, size_t fromPos, const char* search) {
    748729    return findFrom(s, fromPos, search, strlen(search));
    749730}
    750731
    751 int find(const string_res & s, const char * search, size_t searchsize) {
     732int find(const string_res &s, const char* search, size_t searchsize) {
    752733    return findFrom(s, 0, search, searchsize);
    753734}
    754735
    755 int findFrom(const string_res & s, size_t fromPos, const char * search, size_t searchsize) {
     736int findFrom(const string_res &s, size_t fromPos, const char* search, size_t searchsize) {
    756737
    757738    /* Remaining implementations essentially ported from Sunjay's work */
     
    790771}
    791772
    792 bool includes(const string_res & s, const string_res & search) {
     773bool includes(const string_res &s, const string_res &search) {
    793774    return includes(s, search.Handle.s, search.Handle.lnth);
    794775}
    795776
    796 bool includes(const string_res & s, const char * search) {
     777bool includes(const string_res &s, const char* search) {
    797778    return includes(s, search, strlen(search));
    798779}
    799780
    800 bool includes(const string_res & s, const char * search, size_t searchsize) {
     781bool includes(const string_res &s, const char* search, size_t searchsize) {
    801782    return find(s, search, searchsize) < s.Handle.lnth;
    802783}
    803784
    804 bool startsWith(const string_res & s, const string_res & prefix) {
     785bool startsWith(const string_res &s, const string_res &prefix) {
    805786    return startsWith(s, prefix.Handle.s, prefix.Handle.lnth);
    806787}
    807788
    808 bool startsWith(const string_res & s, const char * prefix) {
     789bool startsWith(const string_res &s, const char* prefix) {
    809790    return startsWith(s, prefix, strlen(prefix));
    810791}
    811792
    812 bool startsWith(const string_res & s, const char * prefix, size_t prefixsize) {
     793bool startsWith(const string_res &s, const char* prefix, size_t prefixsize) {
    813794    if (s.Handle.lnth < prefixsize) {
    814795        return false;
     
    817798}
    818799
    819 bool endsWith(const string_res & s, const string_res & suffix) {
     800bool endsWith(const string_res &s, const string_res &suffix) {
    820801    return endsWith(s, suffix.Handle.s, suffix.Handle.lnth);
    821802}
    822803
    823 bool endsWith(const string_res & s, const char * suffix) {
     804bool endsWith(const string_res &s, const char* suffix) {
    824805    return endsWith(s, suffix, strlen(suffix));
    825806}
    826807
    827 bool endsWith(const string_res & s, const char * suffix, size_t suffixsize) {
     808bool endsWith(const string_res &s, const char* suffix, size_t suffixsize) {
    828809    if (s.Handle.lnth < suffixsize) {
    829810        return false;
     
    841822// charclass, include, exclude
    842823
    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 };
     824void ?{}( charclass_res & this, const string_res & chars) {
     825    (this){ chars.Handle.s, chars.Handle.lnth };
     826}
     827
     828void ?{}( charclass_res & this, const char * chars ) {
     829    (this){ chars, strlen(chars) };
     830}
     831
     832void ?{}( charclass_res & this, const char * chars, size_t charssize ) {
     833    (this.chars){ chars, charssize };
    853834    // now sort it ?
    854835}
    855836
    856 void ^?{}( charclass_res & s ) {
    857     ^(s.chars){};
     837void ^?{}( charclass_res & this ) {
     838    ^(this.chars){};
    858839}
    859840
     
    863844}
    864845
    865 int exclude(const string_res & s, const charclass_res & mask) {
     846int exclude(const string_res &s, const charclass_res &mask) {
    866847    for ( i; size(s) ) {
    867848        if ( test(mask, s[i]) ) return i;
     
    870851}
    871852
    872 int include(const string_res & s, const charclass_res & mask) {
     853int include(const string_res &s, const charclass_res &mask) {
    873854    for ( i; size(s) ) {
    874855        if ( ! test(mask, s[i]) ) return i;
     
    882863// Add a new HandleNode node n after the current HandleNode node.
    883864
    884 static void AddThisAfter( HandleNode & s, HandleNode & n ) with(s) {
    885 #ifdef VbyteDebug
    886     serr | "enter:AddThisAfter, s:" | &s | " n:" | &n;
     865static void AddThisAfter( HandleNode & this, HandleNode & n ) with(this) {
     866#ifdef VbyteDebug
     867    serr | "enter:AddThisAfter, this:" | &this | " n:" | &n;
    887868#endif // VbyteDebug
    888869    // 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).
    889870    verify( n.ulink != 0p );
    890     verify( s.ulink == n.ulink );
     871    verify( this.ulink == n.ulink );
    891872    flink = n.flink;
    892873    blink = &n;
    893     n.flink->blink = &s;
    894     n.flink = &s;
     874    n.flink->blink = &this;
     875    n.flink = &this;
    895876#ifdef VbyteDebug
    896877    {
     
    913894// Delete the current HandleNode node.
    914895
    915 static void DeleteNode( HandleNode & s ) with(s) {
    916 #ifdef VbyteDebug
    917     serr | "enter:DeleteNode, s:" | &s;
     896static void DeleteNode( HandleNode & this ) with(this) {
     897#ifdef VbyteDebug
     898    serr | "enter:DeleteNode, this:" | &this;
    918899#endif // VbyteDebug
    919900    flink->blink = blink;
     
    925906
    926907
     908
    927909// Allocates specified storage for a string from byte-string area. If not enough space remains to perform the
    928910// allocation, the garbage collection routine is called.
    929911
    930 static char * VbyteAlloc( VbyteHeap & s, int size ) with(s) {
     912static char * VbyteAlloc( VbyteHeap & this, int size ) with(this) {
    931913#ifdef VbyteDebug
    932914    serr | "enter:VbyteAlloc, size:" | size;
     
    936918
    937919    NoBytes = ( uintptr_t )EndVbyte + size;
    938     if ( NoBytes > ( uintptr_t )ExtVbyte ) {                    // enough room for new byte-string ?
    939                 garbage( s, size );                                                             // firer up the garbage collector
     920    if ( NoBytes > ( uintptr_t )ExtVbyte ) {            // enough room for new byte-string ?
     921                garbage( this, size );                                  // firer up the garbage collector
    940922                verify( (( uintptr_t )EndVbyte + size) <= ( uintptr_t )ExtVbyte  && "garbage run did not free up required space" );
    941923    } // if
     
    957939// VbyteAlloc to claim the new space, while doing optimal copying from old to new, then free old.
    958940
    959 static char * VbyteTryAdjustLast( VbyteHeap & s, int delta ) with(s) {
     941static char * VbyteTryAdjustLast( VbyteHeap & this, int delta ) with(this) {
     942
    960943    if ( ( uintptr_t )EndVbyte + delta <= ( uintptr_t )ExtVbyte ) {
    961944        // room available
     
    978961// the address in the byte string area.
    979962
    980 static void MoveThisAfter( HandleNode & s, const HandleNode  & h ) with(s) {
    981 #ifdef VbyteDebug
    982     serr | "enter:MoveThisAfter, s:" | & s | " h:" | & h;
     963static void MoveThisAfter( HandleNode & this, const HandleNode  & h ) with(this) {
     964#ifdef VbyteDebug
     965    serr | "enter:MoveThisAfter, this:" | & this | " h:" | & h;
    983966#endif // VbyteDebug
    984967    verify( h.ulink != 0p );
    985     verify( s.ulink == h.ulink );
     968    verify( this.ulink == h.ulink );
    986969    if ( s < h.s ) {                                    // check argument values
    987970                // serr | "VbyteSM: Error - Cannot move byte string starting at:" | s | " after byte string starting at:"
     
    993976    HandleNode *i;
    994977    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 );
    998981    } // if
    999982#ifdef VbyteDebug
     
    10751058// the containing string has been moved. Hence, they only require that their string pointers be adjusted.
    10761059
    1077 void compaction(VbyteHeap & s) with(s) {
     1060void compaction(VbyteHeap & this) with(this) {
    10781061    HandleNode *h;
    10791062    char *obase, *nbase, *limit;
     
    11151098// the heap.  The heap is then compacted in the existing heap or into the newly allocated heap.
    11161099
    1117 void garbage(VbyteHeap & s, int minreq ) with(s) {
     1100void garbage(VbyteHeap & this, int minreq ) with(this) {
    11181101#ifdef VbyteDebug
    11191102    serr | "enter:garbage";
     
    11411124    if ( ( double ) AmountFree < ( CurrSize * heap_expansion_freespace_threshold ) || AmountFree < minreq ) {   // free space less than threshold or not enough to serve cur request
    11421125
    1143                 extend( s, max( CurrSize, minreq ) );                           // extend the heap
     1126                extend( this, max( CurrSize, minreq ) );                                // extend the heap
    11441127
    11451128                        //  Peter says, "This needs work before it should be used."
     
    11501133
    11511134    } else {
    1152         compaction(s);                                  // in-place
     1135        compaction(this);                                       // in-place
    11531136    }// if
    11541137#ifdef VbyteDebug
     
    11761159// area is deleted.
    11771160
    1178 void extend( VbyteHeap & s, int size ) with (s) {
     1161void extend( VbyteHeap & this, int size ) with (this) {
    11791162#ifdef VbyteDebug
    11801163    serr | "enter:extend, size:" | size;
     
    11881171    StartVbyte = EndVbyte = TEMP_ALLOC(char, CurrSize);
    11891172    ExtVbyte = (void *)( StartVbyte + CurrSize );
    1190     compaction(s);                                      // copy from old heap to new & adjust pointers to new heap
     1173    compaction(this);                                   // copy from old heap to new & adjust pointers to new heap
    11911174    free( OldStartVbyte );                              // release old heap
    11921175#ifdef VbyteDebug
  • libcfa/src/collections/string_res.hfa

    rf988834 r59c8dff  
    1010// Created On       : Fri Sep 03 11:00:00 2021
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Jan  4 11:28:06 2024
    13 // Update Count     : 27
     12// Last Modified On : Sat Aug 12 15:45:47 2023
     13// Update Count     : 2
    1414//
    1515
     
    7070
    7171// Getters
    72 size_t size(const string_res & s);
     72size_t size(const string_res &s);
    7373
    7474// Constructors, Assignment Operators, Destructor
    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)
     75void ?{}(string_res &s); // empty string
     76void ?{}(string_res &s, const char* buffer, size_t bsize); // copy specific length from buffer
     77static inline void ?{}(string_res &s, const char* rhs) { // copy from string literal (NULL-terminated)
    7878    (s){ rhs, strlen(rhs) };
    7979}
    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
     81void ?{}(string_res &s, const string_res & s2) = void;
     82void ?{}(string_res &s, string_res & s2) = void;
    8783
    8884enum 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 & s, const string_res & src, StrResInitMode mode ) {
     85void ?{}(string_res &s, const string_res & src, StrResInitMode, size_t start, size_t end );
     86static inline void ?{}(string_res &s, const string_res & src, StrResInitMode mode ) {
    9187    ?{}( s, src, mode, 0, size(src));
    9288}
    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
     90string_res & assign(string_res &s, const char* buffer, size_t bsize); // copy specific length from buffer
     91static inline string_res & ?=?(string_res &s, const char* other) {  // copy from string literal (NULL-terminated)
     92    return assign(s, other, strlen(other));
     93}
     94string_res & ?=?(string_res &s, const string_res &other);
     95string_res & ?=?(string_res &s, string_res &other);
     96string_res & ?=?(string_res &s, char other);
     97
     98void ^?{}(string_res &s);
    10799
    108100// 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 );
     101ofstream & ?|?(ofstream &out, const string_res &s);
     102void ?|?(ofstream &out, const string_res &s);
     103ifstream & ?|?(ifstream &in, string_res &s);
     104void ?|?( ifstream & in, string_res & this );
    113105
    114106struct _Istream_Rstr {
     
    121113        _Istream_Rstr wdi( unsigned int rwd, string_res & s ) { return (_Istream_Rstr)@{ &s, {{0p}, rwd, {.flags.rwd : true}} }; }
    122114        _Istream_Rstr getline( string_res & s, const char delimiter = '\n' ) {
    123                 return (_Istream_Rstr)@{ &s, {{.delimiters : { delimiter, '\0' } }, -1, {.flags.delimiter : true, .flags.inex : true}} };
     115                return (_Istream_Rstr)@{ &s, {{.delimiter : { delimiter, '\0' } }, -1, {.flags.delimiter : true, .flags.inex : true}} };
    124116        }
    125117        _Istream_Rstr & getline( _Istream_Rstr & fmt, const char delimiter = '\n' ) {
    126                 fmt.delimiters[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;
    127119        }
    128120        _Istream_Rstr incl( const char scanset[], string_res & s ) { return (_Istream_Rstr)@{ &s, {{scanset}, -1, {.flags.inex : false}} }; }
     
    137129
    138130// 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);
     131void append(string_res &s, const char* buffer, size_t bsize);
     132void ?+=?(string_res &s, char other); // append a character
     133void ?+=?(string_res &s, const string_res &s2); // append-concatenate to first string
     134static inline void ?+=?(string_res &s, const char* other) {
     135    append( s, other, strlen(other) );
     136}
    152137
    153138// Character access
    154 void assignAt(const string_res & s, size_t index, char val);
    155 char ?[?](const string_res & s, size_t index); // Mike changed to ret by val from Sunjay's ref, to match Peter's
    156 //char codePointAt(const string_res & s, size_t index); // revisit under Unicode
     139void assignAt(const string_res &s, size_t index, char val);
     140char ?[?](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
    157142
    158143// Comparisons
    159 int  strcmp (const string_res &, const string_res &);
     144int  cmp (const string_res &, const string_res &);
    160145bool ?==?(const string_res &, const string_res &);
    161146bool ?!=?(const string_res &, const string_res &);
     
    165150bool ?<? (const string_res &, const string_res &);
    166151
    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 *, const string_res &);
    177 bool ?!=?(const char *, const string_res &);
    178 bool ?>? (const char *, const string_res &);
    179 bool ?>=?(const char *, const string_res &);
    180 bool ?<=?(const char *, const string_res &);
    181 bool ?<? (const char *, const string_res &);
     152int  cmp (const string_res &, const char*);
     153bool ?==?(const string_res &, const char*);
     154bool ?!=?(const string_res &, const char*);
     155bool ?>? (const string_res &, const char*);
     156bool ?>=?(const string_res &, const char*);
     157bool ?<=?(const string_res &, const char*);
     158bool ?<? (const string_res &, const char*);
     159
     160int  cmp (const char*, const string_res &);
     161bool ?==?(const char*, const string_res &);
     162bool ?!=?(const char*, const string_res &);
     163bool ?>? (const char*, const string_res &);
     164bool ?>=?(const char*, const string_res &);
     165bool ?<=?(const char*, const string_res &);
     166bool ?<? (const char*, const string_res &);
    182167
    183168// String search
    184 bool contains(const string_res & s, char ch); // single character
    185 
    186 int find(const string_res & s, char search);
    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 & s, size_t fromPos, char search);
    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);
     169bool contains(const string_res &s, char ch); // single character
     170
     171int find(const string_res &s, char search);
     172int find(const string_res &s, const string_res &search);
     173int find(const string_res &s, const char* search);
     174int find(const string_res &s, const char* search, size_t searchsize);
     175
     176int findFrom(const string_res &s, size_t fromPos, char search);
     177int findFrom(const string_res &s, size_t fromPos, const string_res &search);
     178int findFrom(const string_res &s, size_t fromPos, const char* search);
     179int findFrom(const string_res &s, size_t fromPos, const char* search, size_t searchsize);
     180
     181bool includes(const string_res &s, const string_res &search);
     182bool includes(const string_res &s, const char* search);
     183bool includes(const string_res &s, const char* search, size_t searchsize);
     184
     185bool startsWith(const string_res &s, const string_res &prefix);
     186bool startsWith(const string_res &s, const char* prefix);
     187bool startsWith(const string_res &s, const char* prefix, size_t prefixsize);
     188
     189bool endsWith(const string_res &s, const string_res &suffix);
     190bool endsWith(const string_res &s, const char* suffix);
     191bool endsWith(const string_res &s, const char* suffix, size_t suffixsize);
     192
     193int include(const string_res &s, const charclass_res &mask);
     194int exclude(const string_res &s, const charclass_res &mask);
    210195
    211196// Modifiers
    212 void padStart(string_res & s, size_t n);
    213 void padStart(string_res & s, size_t n, char padding);
    214 void padEnd(string_res & s, size_t n);
     197void padStart(string_res &s, size_t n);
     198void padStart(string_res &s, size_t n, char padding);
     199void padEnd(string_res &s, size_t n);
    215200void padEnd(string_res &s, size_t n, char padding);
    216201
  • libcfa/src/heap.cfa

    rf988834 r59c8dff  
    1010// Created On       : Tue Dec 19 21:58:35 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jan  3 21:30:54 2024
    13 // Update Count     : 1619
     12// Last Modified On : Sat Sep 30 17:31:15 2023
     13// Update Count     : 1617
    1414//
    1515
     
    2727#include "bits/align.hfa"                                                               // libAlign
    2828#include "bits/defs.hfa"                                                                // likely, unlikely
    29 #include "concurrency/kernel/fwd.hfa"                                   // disable_interrupts, enable_interrupts
     29#include "concurrency/kernel/fwd.hfa"                                   // __POLL_PREEMPTION
    3030#include "startup.hfa"                                                                  // STARTUP_PRIORITY_MEMORY
    3131#include "math.hfa"                                                                             // ceiling, min
  • libcfa/src/interpose.cfa

    rf988834 r59c8dff  
    1010// Created On       : Wed Mar 29 16:10:31 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Jan 11 18:45:31 2024
    13 // Update Count     : 218
     12// Last Modified On : Mon Mar 27 21:09:03 2023
     13// Update Count     : 196
    1414//
    1515
     
    1818extern "C" {
    1919#include <dlfcn.h>                                                                              // dlopen, dlsym
    20 //#include <link.h>                                                                             // dl_iterate_phdr
    21 struct dl_phdr_info;
    22 int dl_iterate_phdr( int (*)( struct dl_phdr_info *, size_t, void * ), void * );
    2320#include <execinfo.h>                                                                   // backtrace, messages
    2421}
     
    2623#include "bits/defs.hfa"
    2724#include "bits/signal.hfa"                                                              // sigHandler_?
    28 #include "concurrency/kernel/fwd.hfa"                                   // disable_interrupts, enable_interrupts
    2925#include "startup.hfa"                                                                  // STARTUP_PRIORITY_CORE
    3026#include <assert.h>
     
    9187        void (* exit)( int ) __attribute__(( __noreturn__ ));
    9288        void (* abort)( void ) __attribute__(( __noreturn__ ));
    93         int (* dl_iterate_phdr)( int (*)( struct dl_phdr_info *, size_t, void * ), void * );
    9489} __cabi_libc;
    9590
     
    107102                #pragma GCC diagnostic ignored "-Wdiscarded-qualifiers"
    108103                INTERPOSE_LIBC( abort, version );
    109                 INTERPOSE_LIBC( exit, version );
    110                 INTERPOSE_LIBC( dl_iterate_phdr, version );
     104                INTERPOSE_LIBC( exit , version );
    111105                #pragma GCC diagnostic pop
    112106
     
    156150        }
    157151}
    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 routine
    162         enable_interrupts( false );
    163         return ret;
    164 } // dl_iterate_phdr
    165152
    166153//=============================================================================================
  • libcfa/src/iostream.cfa

    rf988834 r59c8dff  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jan  3 10:53:13 2024
    13 // Update Count     : 1898
     12// Last Modified On : Fri Nov 17 13:33:12 2023
     13// Update Count     : 1853
    1414//
    1515
     
    984984        }
    985985
    986         istype & ?|?( istype & is, _Istream_Cquoted f ) with( f ) {
     986        istype & ?|?( istype & is, _Istream_Cquoted f ) {
    987987                char fmtstr[32];                                                                // storage scanset and format codes
    988988                fmtstr[0] = '%';
     
    992992                bool check = true;
    993993
    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 width
     994                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
    997997                        // wd is buffer bytes available (for input chars + null terminator)
    998998                        // rwd is count of input chars
    999999                        // 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;
    10021002                        pos += sprintf( &fmtstr[pos], "%d", rwd );
    10031003                } // if
    10041004
    10051005                int len = 0;                                                                    // may not be set in fmt
    1006                 char enddelim;
    1007                 if ( ! cstr.flags.inex ) {                                              // => quoted getline
     1006                if ( ! f.flags.inex ) {                                                 // => quoted getline
     1007                        // fprintf( stderr, "quoted\n" );
    10081008                        args = fmt( is, "%*[ \f\n\r\t\v]" );            // remove leading whitespace
    10091009                        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 );
    10121013                        if ( len == 0 || eof( is ) ) goto Eof;
    10131014                } // 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 ) );
    10181020                if ( check && len == rwd && ! eof( is ) ) {             // might not fit
    10191021                        char peek;
    10201022                        fmt( is, "%c", &peek );                                         // check for delimiter
     1023                        // fprintf( stderr, "peek %d '%c'\n", args, peek );
    10211024                        if ( ! eof( is ) ) {
    1022                                 if ( peek != enddelim ) {
     1025                                if ( peek != f.delimiter[0] ) {
    10231026                                        ungetc( is, peek );
    10241027                                        throwResume ExceptionInst( cstring_length );
     
    10271030                } else fmt( is, "%*c" );                                                // remove delimiter
    10281031          Eof: ;
    1029                 if ( rwd > 0 && args == 0 ) cstr.s[0] = '\0';   // read failed => no pattern match => set string to null
     1032                if ( rwd > 0 && args == 0 ) f.s[0] = '\0';              // read failed => no pattern match => set string to null
    10301033                if ( args == 1 && eof( is ) ) {                                 // data but scan ended at EOF
     1034                        // fprintf( stderr, "clear\n" );
    10311035                        clear( is );                                                            // => reset EOF => detect again on next read
    10321036                } // if
     
    10341038        }
    10351039
    1036         istype & ?|?( istype & is, _Istream_Cstr f ) with( f ) {
     1040        istype & ?|?( istype & is, _Istream_Cstr f ) {
    10371041                const char * scanset;
    10381042                size_t nscanset = 0;
    1039                 if ( flags.delimiter ) scanset = delimiters;    // getline ?
     1043                if ( f.flags.delimiter ) scanset = f.delimiter; // getline ?
    10401044                else scanset = f.scanset;
    10411045                if ( scanset ) nscanset = strlen( scanset );
     
    10801084                        if ( f.flags.delimiter ) {                                      // getline
    10811085                                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 );
    10831097                                if ( f.flags.ignore ) args = fmt( is, fmtstr, &len ); // no string argument for '*'
    10841098                                else args = fmt( is, fmtstr, f.s, &len );
     1099                                // fprintf( stderr, "getline %s %d %d %d\n", fmtstr, args, f.wd, eof( is ) );
    10851100                                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 );
    10881104                                        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 );
    10921107                                                        throwResume ExceptionInst( cstring_length );
    10931108                                                } // if
    10941109                                        } // if
    1095                                 } else fmt( is, "%*c" );                                // remove delimiter
     1110                                } else fmt( is, "%*c" );                        // remove delimiter
     1111                          X: ;
    10961112                        } else {
    10971113                                // incl %[xxx],  %*[xxx],  %w[xxx],  %*w[xxx]
  • libcfa/src/iostream.hfa

    rf988834 r59c8dff  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jan  3 10:53:18 2024
    13 // Update Count     : 610
     12// Last Modified On : Wed Nov 15 17:55:31 2023
     13// Update Count     : 596
    1414//
    1515
     
    392392        union {
    393393                const char * scanset;
    394                 char delimiters[3];                                                             // [0] => left, [1] => right
     394                char delimiter[2];
    395395        };
    396396        int wd;                                                                                         // width
     
    412412
    413413struct _Istream_Cquoted {
    414         _Istream_Cstr cstr;
     414        char * s;
     415        inline _Istream_str_base;
    415416}; // _Istream_Cquoted
    416417
     
    418419        // width must include room for null terminator
    419420        _Istream_Cstr wdi( unsigned int wd, char s[] ) { return (_Istream_Cstr)@{ s, { {0p}, wd, {.all : 0} } }; }
     421        // read width does not include null terminator
    420422        _Istream_Cstr wdi( unsigned int wd, unsigned int rwd, char s[] ) {
    421423                if ( wd <= rwd ) throw (cstring_length){ &cstring_length_vt };
    422424                return (_Istream_Cstr)@{ s, { {0p}, rwd, {.flags.rwd : true} } };
    423425        }
    424         _Istream_Cquoted & quoted( _Istream_Cstr & fmt, const char Ldelimiter = '"', const char Rdelimiter = '\0' ) {
    425                 fmt.delimiters[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';
    426428                return (_Istream_Cquoted &)fmt;
    427429        }
    428430        _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; }
    431432        _Istream_Cstr & incl( const char scanset[], _Istream_Cstr & fmt ) { fmt.scanset = scanset; fmt.flags.inex = false; return fmt; }
    432433        _Istream_Cstr & excl( const char scanset[], _Istream_Cstr & fmt ) { fmt.scanset = scanset; fmt.flags.inex = true; return fmt; }
  • src/AST/Attribute.cpp

    rf988834 r59c8dff  
    3838
    3939bool Attribute::isValidOnFuncParam() const {
    40         // Attributes produce GCC errors when they appear on function
    41         // 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.
    4343        std::string norm = normalizedName();
    44         return norm != "aligned" && norm != "packed" && norm != "used";
     44        return norm == "unused" || norm == "noreturn";
    4545}
    4646
  • src/AST/Decl.hpp

    rf988834 r59c8dff  
    2929#include "StorageClasses.hpp"
    3030#include "Visitor.hpp"
     31#include "Common/utility.h"
    3132
    3233// Must be included in *all* AST classes; should be #undef'd at the end of the file
  • src/AST/Pass.proto.hpp

    rf988834 r59c8dff  
    1919#include "Common/Iterate.hpp"
    2020#include "Common/Stats/Heap.h"
    21 #include "Common/utility.h"
    2221namespace ast {
    2322        template<typename core_t> class Pass;
  • src/CodeGen/CodeGenerator.hpp

    rf988834 r59c8dff  
    2121#include "AST/Pass.hpp"          // for WithGuards, WithShortCircuiting, ...
    2222#include "CodeGen/Options.h"     // for Options
    23 #include "Common/Indenter.h"     // for Indenter
    2423
    2524
  • src/Common/utility.h

    rf988834 r59c8dff  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Jan 17 14:40:00 2024
    13 // Update Count     : 54
     12// Last Modified On : Fri Feb 17 15:25:00 2023
     13// Update Count     : 53
    1414//
    1515
     
    1717
    1818#include <cassert>
     19#include <cctype>
    1920#include <algorithm>
     21#include <iostream>
    2022#include <list>
     23#include <memory>
    2124#include <string>
    2225#include <type_traits>
    2326#include <vector>
     27#include <cstring>                                                                              // memcmp
     28
     29#include "Common/Indenter.h"
     30
     31class Expression;
     32
     33/// bring std::move into global scope
     34using std::move;
    2435
    2536/// partner to move that copies any copyable type
    2637template<typename T>
    2738T copy( const T & x ) { return x; }
     39
     40template< typename T >
     41static inline T * maybeClone( const T *orig ) {
     42        if ( orig ) {
     43                return orig->clone();
     44        } else {
     45                return 0;
     46        } // if
     47}
     48
     49template< typename Input_iterator >
     50void 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
     56template< typename Container >
     57void deleteAll( const Container &container ) {
     58        for ( const auto &i : container ) {
     59                delete i;
     60        } // for
     61}
     62
     63template< typename Container >
     64void 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
     75template< typename SrcContainer, typename DestContainer >
     76void 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
     84template< typename SrcContainer, typename DestContainer, typename Predicate >
     85void 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
     94template< typename Container >
     95void 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
     104template < typename T >
     105std::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
     112template < typename T >
     113std::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}
    28129
    29130/// Splice src onto the end of dst, clearing src
     
    42143}
    43144
    44 /// Remove elements that match pred from the container.
     145template< typename... Args >
     146auto filter(Args&&... args) -> decltype(std::copy_if(std::forward<Args>(args)...)) {
     147  return std::copy_if(std::forward<Args>(args)...);
     148}
     149
     150template <typename E, typename UnaryPredicate, template< typename, typename...> class Container, typename... Args >
     151void 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
    45165template<typename Container, typename Pred>
    46166void erase_if( Container & cont, Pred && pred ) {
  • src/InitTweak/FixInit.cpp

    rf988834 r59c8dff  
    581581        }
    582582
    583         if ( nullptr == dtor->env && nullptr != env ) {
    584                 dtor->env = ast::shallowCopy( env );
    585         }
     583        if ( ! dtor->env ) dtor->env = maybeClone( env );
    586584        auto dtorFunc = getDtorFunc( ret, new ast::ExprStmt(loc, dtor ), stmtsToAddBefore );
    587585
  • src/Parser/DeclarationNode.cc

    rf988834 r59c8dff  
    3535#include "Common/SemanticError.h"  // for SemanticError
    3636#include "Common/UniqueName.h"     // for UniqueName
    37 #include "Common/utility.h"        // for copy, spliceBegin
     37#include "Common/utility.h"        // for maybeClone
    3838#include "Parser/ExpressionNode.h" // for ExpressionNode
    3939#include "Parser/InitializerNode.h"// for InitializerNode
     
    4141#include "TypeData.h"              // for TypeData, TypeData::Aggregate_t
    4242#include "TypedefTable.h"          // for TypedefTable
     43
     44class Initializer;
    4345
    4446extern TypedefTable typedefTable;
     
    99101DeclarationNode * DeclarationNode::clone() const {
    100102        DeclarationNode * newnode = new DeclarationNode;
    101         newnode->set_next( maybeCopy( get_next() ) );
     103        newnode->set_next( maybeClone( get_next() ) );
    102104        newnode->name = name ? new string( *name ) : nullptr;
    103105
    104106        newnode->builtin = NoBuiltinType;
    105         newnode->type = maybeCopy( type );
     107        newnode->type = maybeClone( type );
    106108        newnode->inLine = inLine;
    107109        newnode->storageClasses = storageClasses;
    108110        newnode->funcSpecs = funcSpecs;
    109         newnode->bitfieldWidth = maybeCopy( bitfieldWidth );
    110         newnode->enumeratorValue.reset( maybeCopy( enumeratorValue.get() ) );
     111        newnode->bitfieldWidth = maybeClone( bitfieldWidth );
     112        newnode->enumeratorValue.reset( maybeClone( enumeratorValue.get() ) );
    111113        newnode->hasEllipsis = hasEllipsis;
    112114        newnode->linkage = linkage;
    113115        newnode->asmName = maybeCopy( asmName );
    114116        newnode->attributes = attributes;
    115         newnode->initializer = maybeCopy( initializer );
     117        newnode->initializer = maybeClone( initializer );
    116118        newnode->extension = extension;
    117         newnode->asmStmt = maybeCopy( asmStmt );
     119        newnode->asmStmt = maybeClone( asmStmt );
    118120        newnode->error = error;
    119121
    120122//      newnode->variable.name = variable.name ? new string( *variable.name ) : nullptr;
    121123        newnode->variable.tyClass = variable.tyClass;
    122         newnode->variable.assertions = maybeCopy( variable.assertions );
    123         newnode->variable.initializer = maybeCopy( variable.initializer );
    124 
    125         newnode->assert.condition = maybeCopy( assert.condition );
     124        newnode->variable.assertions = maybeClone( variable.assertions );
     125        newnode->variable.initializer = maybeClone( variable.initializer );
     126
     127        newnode->assert.condition = maybeClone( assert.condition );
    126128        newnode->assert.message = maybeCopy( assert.message );
    127129        return newnode;
     
    662664                                dst->base->aggInst.aggregate = src;
    663665                                if ( src->kind == TypeData::Aggregate ) {
    664                                         dst->base->aggInst.params = maybeCopy( src->aggregate.actuals );
     666                                        dst->base->aggInst.params = maybeClone( src->aggregate.actuals );
    665667                                } // if
    666668                                dst->base->qualifiers |= src->qualifiers;
     
    692694                                        if ( o->type->kind == TypeData::Aggregate ) {
    693695                                                type->aggInst.hoistType = o->type->aggregate.body;
    694                                                 type->aggInst.params = maybeCopy( o->type->aggregate.actuals );
     696                                                type->aggInst.params = maybeClone( o->type->aggregate.actuals );
    695697                                        } else {
    696698                                                type->aggInst.hoistType = o->type->enumeration.body;
     
    858860                                p->type->base->aggInst.aggregate = type;
    859861                                if ( type->kind == TypeData::Aggregate ) {
    860                                         p->type->base->aggInst.params = maybeCopy( type->aggregate.actuals );
     862                                        p->type->base->aggInst.params = maybeClone( type->aggregate.actuals );
    861863                                } // if
    862864                                p->type->base->qualifiers |= type->qualifiers;
     
    895897                        lastArray->base->aggInst.aggregate = type;
    896898                        if ( type->kind == TypeData::Aggregate ) {
    897                                 lastArray->base->aggInst.params = maybeCopy( type->aggregate.actuals );
     899                                lastArray->base->aggInst.params = maybeClone( type->aggregate.actuals );
    898900                        } // if
    899901                        lastArray->base->qualifiers |= type->qualifiers;
     
    948950DeclarationNode * DeclarationNode::cloneType( string * name ) {
    949951        DeclarationNode * newnode = newName( name );
    950         newnode->type = maybeCopy( type );
     952        newnode->type = maybeClone( type );
    951953        newnode->copySpecifiers( this );
    952954        return newnode;
     
    982984                } // if
    983985
    984                 newType->forall = maybeCopy( type->forall );
     986                newType->forall = maybeClone( type->forall );
    985987                if ( ! o->type ) {
    986988                        o->type = newType;
  • src/Parser/ParseNode.h

    rf988834 r59c8dff  
    3030#include "Common/SemanticError.h"  // for SemanticError
    3131#include "Common/UniqueName.h"     // for UniqueName
     32#include "Common/utility.h"        // for maybeClone
    3233#include "Parser/parserutility.h"  // for maybeBuild, maybeCopy
    3334
  • src/Parser/TypeData.cc

    rf988834 r59c8dff  
    167167        TypeData * newtype = new TypeData( kind );
    168168        newtype->qualifiers = qualifiers;
    169         newtype->base = maybeCopy( base );
    170         newtype->forall = maybeCopy( forall );
     169        newtype->base = maybeClone( base );
     170        newtype->forall = maybeClone( forall );
    171171
    172172        switch ( kind ) {
     
    185185                break;
    186186        case Array:
    187                 newtype->array.dimension = maybeCopy( array.dimension );
     187                newtype->array.dimension = maybeClone( array.dimension );
    188188                newtype->array.isVarLen = array.isVarLen;
    189189                newtype->array.isStatic = array.isStatic;
    190190                break;
    191191        case Function:
    192                 newtype->function.params = maybeCopy( function.params );
    193                 newtype->function.idList = maybeCopy( function.idList );
    194                 newtype->function.oldDeclList = maybeCopy( function.oldDeclList );
    195                 newtype->function.body = maybeCopy( function.body );
    196                 newtype->function.withExprs = maybeCopy( 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 );
    197197                break;
    198198        case Aggregate:
    199199                newtype->aggregate.kind = aggregate.kind;
    200200                newtype->aggregate.name = aggregate.name ? new string( *aggregate.name ) : nullptr;
    201                 newtype->aggregate.params = maybeCopy( aggregate.params );
    202                 newtype->aggregate.actuals = maybeCopy( aggregate.actuals );
    203                 newtype->aggregate.fields = maybeCopy( aggregate.fields );
     201                newtype->aggregate.params = maybeClone( aggregate.params );
     202                newtype->aggregate.actuals = maybeClone( aggregate.actuals );
     203                newtype->aggregate.fields = maybeClone( aggregate.fields );
    204204                newtype->aggregate.body = aggregate.body;
    205205                newtype->aggregate.anon = aggregate.anon;
     
    208208                break;
    209209        case AggregateInst:
    210                 newtype->aggInst.aggregate = maybeCopy( aggInst.aggregate );
    211                 newtype->aggInst.params = maybeCopy( aggInst.params );
     210                newtype->aggInst.aggregate = maybeClone( aggInst.aggregate );
     211                newtype->aggInst.params = maybeClone( aggInst.params );
    212212                newtype->aggInst.hoistType = aggInst.hoistType;
    213213                break;
    214214        case Enum:
    215215                newtype->enumeration.name = enumeration.name ? new string( *enumeration.name ) : nullptr;
    216                 newtype->enumeration.constants = maybeCopy( enumeration.constants );
     216                newtype->enumeration.constants = maybeClone( enumeration.constants );
    217217                newtype->enumeration.body = enumeration.body;
    218218                newtype->enumeration.anon = enumeration.anon;
     
    221221        case SymbolicInst:
    222222                newtype->symbolic.name = symbolic.name ? new string( *symbolic.name ) : nullptr;
    223                 newtype->symbolic.params = maybeCopy( symbolic.params );
    224                 newtype->symbolic.actuals = maybeCopy( symbolic.actuals );
    225                 newtype->symbolic.assertions = maybeCopy( symbolic.assertions );
     223                newtype->symbolic.params = maybeClone( symbolic.params );
     224                newtype->symbolic.actuals = maybeClone( symbolic.actuals );
     225                newtype->symbolic.assertions = maybeClone( symbolic.assertions );
    226226                newtype->symbolic.isTypedef = symbolic.isTypedef;
    227227                break;
    228228        case Tuple:
    229                 newtype->tuple = maybeCopy( tuple );
     229                newtype->tuple = maybeClone( tuple );
    230230                break;
    231231        case Typeof:
    232232        case Basetypeof:
    233                 newtype->typeexpr = maybeCopy( typeexpr );
     233                newtype->typeexpr = maybeClone( typeexpr );
    234234                break;
    235235        case Vtable:
     
    240240                break;
    241241        case Qualified:
    242                 newtype->qualified.parent = maybeCopy( qualified.parent );
    243                 newtype->qualified.child = maybeCopy( qualified.child );
     242                newtype->qualified.parent = maybeClone( qualified.parent );
     243                newtype->qualified.child = maybeClone( qualified.child );
    244244                break;
    245245        } // switch
  • src/Parser/parser.yy

    rf988834 r59c8dff  
    19601960                        // Append the return type at the start (left-hand-side) to each identifier in the list.
    19611961                        DeclarationNode * ret = new DeclarationNode;
    1962                         ret->type = maybeCopy( $1->type->base );
     1962                        ret->type = maybeClone( $1->type->base );
    19631963                        $$ = $1->appendList( DeclarationNode::newFunction( $3, ret, $6, nullptr ) );
    19641964                }
  • src/Parser/parserutility.h

    rf988834 r59c8dff  
    3636
    3737template<typename node_t>
    38 static inline node_t * maybeCopy( node_t const * node ) {
     38node_t * maybeCopy( node_t const * node ) {
    3939        return node ? ast::shallowCopy( node ) : nullptr;
    4040}
  • src/SymTab/GenImplicitCall.cpp

    rf988834 r59c8dff  
    2525#include "CodeGen/OperatorTable.h"       // for isCtorDtor
    2626#include "Common/UniqueName.h"           // for UniqueName
    27 #include "Common/utility.h"              // for splice
    2827
    2928namespace SymTab {
  • src/Validate/Autogen.cpp

    rf988834 r59c8dff  
    445445
    446446                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();
    450448                ast::ObjectDecl * param = new ast::ObjectDecl(
    451449                        getLocation(), member->name, paramType );
  • src/Validate/ReplaceTypedef.cpp

    rf988834 r59c8dff  
    2525
    2626namespace {
     27
     28bool 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}
    2739
    2840struct ReplaceTypedefCore final :
     
    89101                // by typedef. GCC appears to do the same thing.
    90102                if ( isAtFunctionTop ) {
    91                         erase_if( ret->attributes, []( ast::Attribute const * attr ){
    92                                 return !attr->isValidOnFuncParam();
    93                         } );
     103                        erase_if( ret->attributes, isNonParameterAttribute );
    94104                }
    95105                for ( const auto & attribute : type->attributes ) {
  • tests/Makefile.am

    rf988834 r59c8dff  
    9292        concurrency/channels/parallel_harness.hfa \
    9393        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
    9695
    9796dist-hook:
  • tests/collections/.expect/string-api-coverage.txt

    rf988834 r59c8dff  
    1414true false
    1515true false
    16 1234567
    1716123
    1817hello
    19 hell
    2018hello
    2119world
    2220hello
    2321world
    24 Q
    25 1234567
    26 hello
    27 Q
    28 123
    29 hell
    30 1234567
    31 hello
    32 123
    33 hell
    34225
    3523helloworld
     
    4129hello, friend
    4230bye, friend
    43 ohello
    44 ohell
    45 ohell
    46 omydarling
    47 omy
    48 omy
    49 hellohellohellohello
    5031hellohellohello
    5132QQQ
    5233asdfasdfasdf
    53 lo
    54 hello heliocentric
    5534e
    5635help!!!o
  • tests/collections/.expect/string-compare.txt

    rf988834 r59c8dff  
    11------- string -------
    2 (strcmp(s_, s_) == 0) ok
     2(cmp(s_, s_) == 0) ok
    33(s_ == s_) ok
    44!(s_ != s_) ok
     
    77(s_ <= s_) ok
    88!(s_ < s_) ok
    9 (strcmp("", s_) == 0) ok
     9(cmp("", s_) == 0) ok
    1010("" == s_) ok
    1111!("" != s_) ok
     
    1414("" <= s_) ok
    1515!("" < s_) ok
    16 (strcmp(s_, "") == 0) ok
     16(cmp(s_, "") == 0) ok
    1717(s_ == "") ok
    1818!(s_ != "") ok
     
    2121(s_ <= "") ok
    2222!(s_ < "") ok
    23 (strcmp(s_, s_a) < 0) ok
     23(cmp(s_, s_a) < 0) ok
    2424!(s_ == s_a) ok
    2525(s_ != s_a) ok
     
    2828(s_ <= s_a) ok
    2929(s_ < s_a) ok
    30 (strcmp("", s_a) < 0) ok
     30(cmp("", s_a) < 0) ok
    3131!("" == s_a) ok
    3232("" != s_a) ok
     
    3535("" <= s_a) ok
    3636("" < s_a) ok
    37 (strcmp(s_, "a") < 0) ok
     37(cmp(s_, "a") < 0) ok
    3838!(s_ == "a") ok
    3939(s_ != "a") ok
     
    4242(s_ <= "a") ok
    4343(s_ < "a") ok
    44 (strcmp(s_a, s_) > 0) ok
     44(cmp(s_a, s_) > 0) ok
    4545!(s_a == s_) ok
    4646(s_a != s_) ok
     
    4949!(s_a <= s_) ok
    5050!(s_a < s_) ok
    51 (strcmp("a", s_) > 0) ok
     51(cmp("a", s_) > 0) ok
    5252!("a" == s_) ok
    5353("a" != s_) ok
     
    5656!("a" <= s_) ok
    5757!("a" < s_) ok
    58 (strcmp(s_a, "") > 0) ok
     58(cmp(s_a, "") > 0) ok
    5959!(s_a == "") ok
    6060(s_a != "") ok
     
    6363!(s_a <= "") ok
    6464!(s_a < "") ok
    65 (strcmp(s_, s_aa) < 0) ok
     65(cmp(s_, s_aa) < 0) ok
    6666!(s_ == s_aa) ok
    6767(s_ != s_aa) ok
     
    7070(s_ <= s_aa) ok
    7171(s_ < s_aa) ok
    72 (strcmp("", s_aa) < 0) ok
     72(cmp("", s_aa) < 0) ok
    7373!("" == s_aa) ok
    7474("" != s_aa) ok
     
    7777("" <= s_aa) ok
    7878("" < s_aa) ok
    79 (strcmp(s_, "aa") < 0) ok
     79(cmp(s_, "aa") < 0) ok
    8080!(s_ == "aa") ok
    8181(s_ != "aa") ok
     
    8484(s_ <= "aa") ok
    8585(s_ < "aa") ok
    86 (strcmp(s_aa, s_) > 0) ok
     86(cmp(s_aa, s_) > 0) ok
    8787!(s_aa == s_) ok
    8888(s_aa != s_) ok
     
    9191!(s_aa <= s_) ok
    9292!(s_aa < s_) ok
    93 (strcmp("aa", s_) > 0) ok
     93(cmp("aa", s_) > 0) ok
    9494!("aa" == s_) ok
    9595("aa" != s_) ok
     
    9898!("aa" <= s_) ok
    9999!("aa" < s_) ok
    100 (strcmp(s_aa, "") > 0) ok
     100(cmp(s_aa, "") > 0) ok
    101101!(s_aa == "") ok
    102102(s_aa != "") ok
     
    105105!(s_aa <= "") ok
    106106!(s_aa < "") ok
    107 (strcmp(s_a, s_aa) < 0) ok
     107(cmp(s_a, s_aa) < 0) ok
    108108!(s_a == s_aa) ok
    109109(s_a != s_aa) ok
     
    112112(s_a <= s_aa) ok
    113113(s_a < s_aa) ok
    114 (strcmp("a", s_aa) < 0) ok
     114(cmp("a", s_aa) < 0) ok
    115115!("a" == s_aa) ok
    116116("a" != s_aa) ok
     
    119119("a" <= s_aa) ok
    120120("a" < s_aa) ok
    121 (strcmp(s_a, "aa") < 0) ok
     121(cmp(s_a, "aa") < 0) ok
    122122!(s_a == "aa") ok
    123123(s_a != "aa") ok
     
    126126(s_a <= "aa") ok
    127127(s_a < "aa") ok
    128 (strcmp(s_aa, s_a) > 0) ok
     128(cmp(s_aa, s_a) > 0) ok
    129129!(s_aa == s_a) ok
    130130(s_aa != s_a) ok
     
    133133!(s_aa <= s_a) ok
    134134!(s_aa < s_a) ok
    135 (strcmp("aa", s_a) > 0) ok
     135(cmp("aa", s_a) > 0) ok
    136136!("aa" == s_a) ok
    137137("aa" != s_a) ok
     
    140140!("aa" <= s_a) ok
    141141!("aa" < s_a) ok
    142 (strcmp(s_aa, "a") > 0) ok
     142(cmp(s_aa, "a") > 0) ok
    143143!(s_aa == "a") ok
    144144(s_aa != "a") ok
     
    147147!(s_aa <= "a") ok
    148148!(s_aa < "a") ok
    149 (strcmp(s_a, s_a) == 0) ok
     149(cmp(s_a, s_a) == 0) ok
    150150(s_a == s_a) ok
    151151!(s_a != s_a) ok
     
    154154(s_a <= s_a) ok
    155155!(s_a < s_a) ok
    156 (strcmp("a", s_a) == 0) ok
     156(cmp("a", s_a) == 0) ok
    157157("a" == s_a) ok
    158158!("a" != s_a) ok
     
    161161("a" <= s_a) ok
    162162!("a" < s_a) ok
    163 (strcmp(s_a, "a") == 0) ok
     163(cmp(s_a, "a") == 0) ok
    164164(s_a == "a") ok
    165165!(s_a != "a") ok
     
    168168(s_a <= "a") ok
    169169!(s_a < "a") ok
    170 (strcmp(s_aa, s_aa) == 0) ok
     170(cmp(s_aa, s_aa) == 0) ok
    171171(s_aa == s_aa) ok
    172172!(s_aa != s_aa) ok
     
    175175(s_aa <= s_aa) ok
    176176!(s_aa < s_aa) ok
    177 (strcmp("aa", s_aa) == 0) ok
     177(cmp("aa", s_aa) == 0) ok
    178178("aa" == s_aa) ok
    179179!("aa" != s_aa) ok
     
    182182("aa" <= s_aa) ok
    183183!("aa" < s_aa) ok
    184 (strcmp(s_aa, "aa") == 0) ok
     184(cmp(s_aa, "aa") == 0) ok
    185185(s_aa == "aa") ok
    186186!(s_aa != "aa") ok
     
    189189(s_aa <= "aa") ok
    190190!(s_aa < "aa") ok
    191 (strcmp(s_a, s_b) < 0) ok
     191(cmp(s_a, s_b) < 0) ok
    192192!(s_a == s_b) ok
    193193(s_a != s_b) ok
     
    196196(s_a <= s_b) ok
    197197(s_a < s_b) ok
    198 (strcmp("a", s_b) < 0) ok
     198(cmp("a", s_b) < 0) ok
    199199!("a" == s_b) ok
    200200("a" != s_b) ok
     
    203203("a" <= s_b) ok
    204204("a" < s_b) ok
    205 (strcmp(s_a, "b") < 0) ok
     205(cmp(s_a, "b") < 0) ok
    206206!(s_a == "b") ok
    207207(s_a != "b") ok
     
    210210(s_a <= "b") ok
    211211(s_a < "b") ok
    212 (strcmp(s_b, s_a) > 0) ok
     212(cmp(s_b, s_a) > 0) ok
    213213!(s_b == s_a) ok
    214214(s_b != s_a) ok
     
    217217!(s_b <= s_a) ok
    218218!(s_b < s_a) ok
    219 (strcmp("b", s_a) > 0) ok
     219(cmp("b", s_a) > 0) ok
    220220!("b" == s_a) ok
    221221("b" != s_a) ok
     
    224224!("b" <= s_a) ok
    225225!("b" < s_a) ok
    226 (strcmp(s_b, "a") > 0) ok
     226(cmp(s_b, "a") > 0) ok
    227227!(s_b == "a") ok
    228228(s_b != "a") ok
     
    231231!(s_b <= "a") ok
    232232!(s_b < "a") ok
    233 (strcmp(s_a, s_ba) < 0) ok
     233(cmp(s_a, s_ba) < 0) ok
    234234!(s_a == s_ba) ok
    235235(s_a != s_ba) ok
     
    238238(s_a <= s_ba) ok
    239239(s_a < s_ba) ok
    240 (strcmp("a", s_ba) < 0) ok
     240(cmp("a", s_ba) < 0) ok
    241241!("a" == s_ba) ok
    242242("a" != s_ba) ok
     
    245245("a" <= s_ba) ok
    246246("a" < s_ba) ok
    247 (strcmp(s_a, "ba") < 0) ok
     247(cmp(s_a, "ba") < 0) ok
    248248!(s_a == "ba") ok
    249249(s_a != "ba") ok
     
    252252(s_a <= "ba") ok
    253253(s_a < "ba") ok
    254 (strcmp(s_ba, s_a) > 0) ok
     254(cmp(s_ba, s_a) > 0) ok
    255255!(s_ba == s_a) ok
    256256(s_ba != s_a) ok
     
    259259!(s_ba <= s_a) ok
    260260!(s_ba < s_a) ok
    261 (strcmp("ba", s_a) > 0) ok
     261(cmp("ba", s_a) > 0) ok
    262262!("ba" == s_a) ok
    263263("ba" != s_a) ok
     
    266266!("ba" <= s_a) ok
    267267!("ba" < s_a) ok
    268 (strcmp(s_ba, "a") > 0) ok
     268(cmp(s_ba, "a") > 0) ok
    269269!(s_ba == "a") ok
    270270(s_ba != "a") ok
     
    273273!(s_ba <= "a") ok
    274274!(s_ba < "a") ok
    275 (strcmp(s_aa, s_ab) < 0) ok
     275(cmp(s_aa, s_ab) < 0) ok
    276276!(s_aa == s_ab) ok
    277277(s_aa != s_ab) ok
     
    280280(s_aa <= s_ab) ok
    281281(s_aa < s_ab) ok
    282 (strcmp("aa", s_ab) < 0) ok
     282(cmp("aa", s_ab) < 0) ok
    283283!("aa" == s_ab) ok
    284284("aa" != s_ab) ok
     
    287287("aa" <= s_ab) ok
    288288("aa" < s_ab) ok
    289 (strcmp(s_aa, "ab") < 0) ok
     289(cmp(s_aa, "ab") < 0) ok
    290290!(s_aa == "ab") ok
    291291(s_aa != "ab") ok
     
    294294(s_aa <= "ab") ok
    295295(s_aa < "ab") ok
    296 (strcmp(s_ab, s_aa) > 0) ok
     296(cmp(s_ab, s_aa) > 0) ok
    297297!(s_ab == s_aa) ok
    298298(s_ab != s_aa) ok
     
    301301!(s_ab <= s_aa) ok
    302302!(s_ab < s_aa) ok
    303 (strcmp("ab", s_aa) > 0) ok
     303(cmp("ab", s_aa) > 0) ok
    304304!("ab" == s_aa) ok
    305305("ab" != s_aa) ok
     
    308308!("ab" <= s_aa) ok
    309309!("ab" < s_aa) ok
    310 (strcmp(s_ab, "aa") > 0) ok
     310(cmp(s_ab, "aa") > 0) ok
    311311!(s_ab == "aa") ok
    312312(s_ab != "aa") ok
     
    315315!(s_ab <= "aa") ok
    316316!(s_ab < "aa") ok
    317 (strcmp(s_ba, s_bb) < 0) ok
     317(cmp(s_ba, s_bb) < 0) ok
    318318!(s_ba == s_bb) ok
    319319(s_ba != s_bb) ok
     
    322322(s_ba <= s_bb) ok
    323323(s_ba < s_bb) ok
    324 (strcmp("ba", s_bb) < 0) ok
     324(cmp("ba", s_bb) < 0) ok
    325325!("ba" == s_bb) ok
    326326("ba" != s_bb) ok
     
    329329("ba" <= s_bb) ok
    330330("ba" < s_bb) ok
    331 (strcmp(s_ba, "bb") < 0) ok
     331(cmp(s_ba, "bb") < 0) ok
    332332!(s_ba == "bb") ok
    333333(s_ba != "bb") ok
     
    336336(s_ba <= "bb") ok
    337337(s_ba < "bb") ok
    338 (strcmp(s_bb, s_ba) > 0) ok
     338(cmp(s_bb, s_ba) > 0) ok
    339339!(s_bb == s_ba) ok
    340340(s_bb != s_ba) ok
     
    343343!(s_bb <= s_ba) ok
    344344!(s_bb < s_ba) ok
    345 (strcmp("bb", s_ba) > 0) ok
     345(cmp("bb", s_ba) > 0) ok
    346346!("bb" == s_ba) ok
    347347("bb" != s_ba) ok
     
    350350!("bb" <= s_ba) ok
    351351!("bb" < s_ba) ok
    352 (strcmp(s_bb, "ba") > 0) ok
     352(cmp(s_bb, "ba") > 0) ok
    353353!(s_bb == "ba") ok
    354354(s_bb != "ba") ok
     
    357357!(s_bb <= "ba") ok
    358358!(s_bb < "ba") ok
    359 (strcmp(s_aa, s_b) < 0) ok
     359(cmp(s_aa, s_b) < 0) ok
    360360!(s_aa == s_b) ok
    361361(s_aa != s_b) ok
     
    364364(s_aa <= s_b) ok
    365365(s_aa < s_b) ok
    366 (strcmp("aa", s_b) < 0) ok
     366(cmp("aa", s_b) < 0) ok
    367367!("aa" == s_b) ok
    368368("aa" != s_b) ok
     
    371371("aa" <= s_b) ok
    372372("aa" < s_b) ok
    373 (strcmp(s_aa, "b") < 0) ok
     373(cmp(s_aa, "b") < 0) ok
    374374!(s_aa == "b") ok
    375375(s_aa != "b") ok
     
    378378(s_aa <= "b") ok
    379379(s_aa < "b") ok
    380 (strcmp(s_b, s_aa) > 0) ok
     380(cmp(s_b, s_aa) > 0) ok
    381381!(s_b == s_aa) ok
    382382(s_b != s_aa) ok
     
    385385!(s_b <= s_aa) ok
    386386!(s_b < s_aa) ok
    387 (strcmp("b", s_aa) > 0) ok
     387(cmp("b", s_aa) > 0) ok
    388388!("b" == s_aa) ok
    389389("b" != s_aa) ok
     
    392392!("b" <= s_aa) ok
    393393!("b" < s_aa) ok
    394 (strcmp(s_b, "aa") > 0) ok
     394(cmp(s_b, "aa") > 0) ok
    395395!(s_b == "aa") ok
    396396(s_b != "aa") ok
     
    400400!(s_b < "aa") ok
    401401------- string_res -------
    402 (strcmp(s_, s_) == 0) ok
     402(cmp(s_, s_) == 0) ok
    403403(s_ == s_) ok
    404404!(s_ != s_) ok
     
    407407(s_ <= s_) ok
    408408!(s_ < s_) ok
    409 (strcmp("", s_) == 0) ok
     409(cmp("", s_) == 0) ok
    410410("" == s_) ok
    411411!("" != s_) ok
     
    414414("" <= s_) ok
    415415!("" < s_) ok
    416 (strcmp(s_, "") == 0) ok
     416(cmp(s_, "") == 0) ok
    417417(s_ == "") ok
    418418!(s_ != "") ok
     
    421421(s_ <= "") ok
    422422!(s_ < "") ok
    423 (strcmp(s_, s_a) < 0) ok
     423(cmp(s_, s_a) < 0) ok
    424424!(s_ == s_a) ok
    425425(s_ != s_a) ok
     
    428428(s_ <= s_a) ok
    429429(s_ < s_a) ok
    430 (strcmp("", s_a) < 0) ok
     430(cmp("", s_a) < 0) ok
    431431!("" == s_a) ok
    432432("" != s_a) ok
     
    435435("" <= s_a) ok
    436436("" < s_a) ok
    437 (strcmp(s_, "a") < 0) ok
     437(cmp(s_, "a") < 0) ok
    438438!(s_ == "a") ok
    439439(s_ != "a") ok
     
    442442(s_ <= "a") ok
    443443(s_ < "a") ok
    444 (strcmp(s_a, s_) > 0) ok
     444(cmp(s_a, s_) > 0) ok
    445445!(s_a == s_) ok
    446446(s_a != s_) ok
     
    449449!(s_a <= s_) ok
    450450!(s_a < s_) ok
    451 (strcmp("a", s_) > 0) ok
     451(cmp("a", s_) > 0) ok
    452452!("a" == s_) ok
    453453("a" != s_) ok
     
    456456!("a" <= s_) ok
    457457!("a" < s_) ok
    458 (strcmp(s_a, "") > 0) ok
     458(cmp(s_a, "") > 0) ok
    459459!(s_a == "") ok
    460460(s_a != "") ok
     
    463463!(s_a <= "") ok
    464464!(s_a < "") ok
    465 (strcmp(s_, s_aa) < 0) ok
     465(cmp(s_, s_aa) < 0) ok
    466466!(s_ == s_aa) ok
    467467(s_ != s_aa) ok
     
    470470(s_ <= s_aa) ok
    471471(s_ < s_aa) ok
    472 (strcmp("", s_aa) < 0) ok
     472(cmp("", s_aa) < 0) ok
    473473!("" == s_aa) ok
    474474("" != s_aa) ok
     
    477477("" <= s_aa) ok
    478478("" < s_aa) ok
    479 (strcmp(s_, "aa") < 0) ok
     479(cmp(s_, "aa") < 0) ok
    480480!(s_ == "aa") ok
    481481(s_ != "aa") ok
     
    484484(s_ <= "aa") ok
    485485(s_ < "aa") ok
    486 (strcmp(s_aa, s_) > 0) ok
     486(cmp(s_aa, s_) > 0) ok
    487487!(s_aa == s_) ok
    488488(s_aa != s_) ok
     
    491491!(s_aa <= s_) ok
    492492!(s_aa < s_) ok
    493 (strcmp("aa", s_) > 0) ok
     493(cmp("aa", s_) > 0) ok
    494494!("aa" == s_) ok
    495495("aa" != s_) ok
     
    498498!("aa" <= s_) ok
    499499!("aa" < s_) ok
    500 (strcmp(s_aa, "") > 0) ok
     500(cmp(s_aa, "") > 0) ok
    501501!(s_aa == "") ok
    502502(s_aa != "") ok
     
    505505!(s_aa <= "") ok
    506506!(s_aa < "") ok
    507 (strcmp(s_a, s_aa) < 0) ok
     507(cmp(s_a, s_aa) < 0) ok
    508508!(s_a == s_aa) ok
    509509(s_a != s_aa) ok
     
    512512(s_a <= s_aa) ok
    513513(s_a < s_aa) ok
    514 (strcmp("a", s_aa) < 0) ok
     514(cmp("a", s_aa) < 0) ok
    515515!("a" == s_aa) ok
    516516("a" != s_aa) ok
     
    519519("a" <= s_aa) ok
    520520("a" < s_aa) ok
    521 (strcmp(s_a, "aa") < 0) ok
     521(cmp(s_a, "aa") < 0) ok
    522522!(s_a == "aa") ok
    523523(s_a != "aa") ok
     
    526526(s_a <= "aa") ok
    527527(s_a < "aa") ok
    528 (strcmp(s_aa, s_a) > 0) ok
     528(cmp(s_aa, s_a) > 0) ok
    529529!(s_aa == s_a) ok
    530530(s_aa != s_a) ok
     
    533533!(s_aa <= s_a) ok
    534534!(s_aa < s_a) ok
    535 (strcmp("aa", s_a) > 0) ok
     535(cmp("aa", s_a) > 0) ok
    536536!("aa" == s_a) ok
    537537("aa" != s_a) ok
     
    540540!("aa" <= s_a) ok
    541541!("aa" < s_a) ok
    542 (strcmp(s_aa, "a") > 0) ok
     542(cmp(s_aa, "a") > 0) ok
    543543!(s_aa == "a") ok
    544544(s_aa != "a") ok
     
    547547!(s_aa <= "a") ok
    548548!(s_aa < "a") ok
    549 (strcmp(s_a, s_a) == 0) ok
     549(cmp(s_a, s_a) == 0) ok
    550550(s_a == s_a) ok
    551551!(s_a != s_a) ok
     
    554554(s_a <= s_a) ok
    555555!(s_a < s_a) ok
    556 (strcmp("a", s_a) == 0) ok
     556(cmp("a", s_a) == 0) ok
    557557("a" == s_a) ok
    558558!("a" != s_a) ok
     
    561561("a" <= s_a) ok
    562562!("a" < s_a) ok
    563 (strcmp(s_a, "a") == 0) ok
     563(cmp(s_a, "a") == 0) ok
    564564(s_a == "a") ok
    565565!(s_a != "a") ok
     
    568568(s_a <= "a") ok
    569569!(s_a < "a") ok
    570 (strcmp(s_aa, s_aa) == 0) ok
     570(cmp(s_aa, s_aa) == 0) ok
    571571(s_aa == s_aa) ok
    572572!(s_aa != s_aa) ok
     
    575575(s_aa <= s_aa) ok
    576576!(s_aa < s_aa) ok
    577 (strcmp("aa", s_aa) == 0) ok
     577(cmp("aa", s_aa) == 0) ok
    578578("aa" == s_aa) ok
    579579!("aa" != s_aa) ok
     
    582582("aa" <= s_aa) ok
    583583!("aa" < s_aa) ok
    584 (strcmp(s_aa, "aa") == 0) ok
     584(cmp(s_aa, "aa") == 0) ok
    585585(s_aa == "aa") ok
    586586!(s_aa != "aa") ok
     
    589589(s_aa <= "aa") ok
    590590!(s_aa < "aa") ok
    591 (strcmp(s_a, s_b) < 0) ok
     591(cmp(s_a, s_b) < 0) ok
    592592!(s_a == s_b) ok
    593593(s_a != s_b) ok
     
    596596(s_a <= s_b) ok
    597597(s_a < s_b) ok
    598 (strcmp("a", s_b) < 0) ok
     598(cmp("a", s_b) < 0) ok
    599599!("a" == s_b) ok
    600600("a" != s_b) ok
     
    603603("a" <= s_b) ok
    604604("a" < s_b) ok
    605 (strcmp(s_a, "b") < 0) ok
     605(cmp(s_a, "b") < 0) ok
    606606!(s_a == "b") ok
    607607(s_a != "b") ok
     
    610610(s_a <= "b") ok
    611611(s_a < "b") ok
    612 (strcmp(s_b, s_a) > 0) ok
     612(cmp(s_b, s_a) > 0) ok
    613613!(s_b == s_a) ok
    614614(s_b != s_a) ok
     
    617617!(s_b <= s_a) ok
    618618!(s_b < s_a) ok
    619 (strcmp("b", s_a) > 0) ok
     619(cmp("b", s_a) > 0) ok
    620620!("b" == s_a) ok
    621621("b" != s_a) ok
     
    624624!("b" <= s_a) ok
    625625!("b" < s_a) ok
    626 (strcmp(s_b, "a") > 0) ok
     626(cmp(s_b, "a") > 0) ok
    627627!(s_b == "a") ok
    628628(s_b != "a") ok
     
    631631!(s_b <= "a") ok
    632632!(s_b < "a") ok
    633 (strcmp(s_a, s_ba) < 0) ok
     633(cmp(s_a, s_ba) < 0) ok
    634634!(s_a == s_ba) ok
    635635(s_a != s_ba) ok
     
    638638(s_a <= s_ba) ok
    639639(s_a < s_ba) ok
    640 (strcmp("a", s_ba) < 0) ok
     640(cmp("a", s_ba) < 0) ok
    641641!("a" == s_ba) ok
    642642("a" != s_ba) ok
     
    645645("a" <= s_ba) ok
    646646("a" < s_ba) ok
    647 (strcmp(s_a, "ba") < 0) ok
     647(cmp(s_a, "ba") < 0) ok
    648648!(s_a == "ba") ok
    649649(s_a != "ba") ok
     
    652652(s_a <= "ba") ok
    653653(s_a < "ba") ok
    654 (strcmp(s_ba, s_a) > 0) ok
     654(cmp(s_ba, s_a) > 0) ok
    655655!(s_ba == s_a) ok
    656656(s_ba != s_a) ok
     
    659659!(s_ba <= s_a) ok
    660660!(s_ba < s_a) ok
    661 (strcmp("ba", s_a) > 0) ok
     661(cmp("ba", s_a) > 0) ok
    662662!("ba" == s_a) ok
    663663("ba" != s_a) ok
     
    666666!("ba" <= s_a) ok
    667667!("ba" < s_a) ok
    668 (strcmp(s_ba, "a") > 0) ok
     668(cmp(s_ba, "a") > 0) ok
    669669!(s_ba == "a") ok
    670670(s_ba != "a") ok
     
    673673!(s_ba <= "a") ok
    674674!(s_ba < "a") ok
    675 (strcmp(s_aa, s_ab) < 0) ok
     675(cmp(s_aa, s_ab) < 0) ok
    676676!(s_aa == s_ab) ok
    677677(s_aa != s_ab) ok
     
    680680(s_aa <= s_ab) ok
    681681(s_aa < s_ab) ok
    682 (strcmp("aa", s_ab) < 0) ok
     682(cmp("aa", s_ab) < 0) ok
    683683!("aa" == s_ab) ok
    684684("aa" != s_ab) ok
     
    687687("aa" <= s_ab) ok
    688688("aa" < s_ab) ok
    689 (strcmp(s_aa, "ab") < 0) ok
     689(cmp(s_aa, "ab") < 0) ok
    690690!(s_aa == "ab") ok
    691691(s_aa != "ab") ok
     
    694694(s_aa <= "ab") ok
    695695(s_aa < "ab") ok
    696 (strcmp(s_ab, s_aa) > 0) ok
     696(cmp(s_ab, s_aa) > 0) ok
    697697!(s_ab == s_aa) ok
    698698(s_ab != s_aa) ok
     
    701701!(s_ab <= s_aa) ok
    702702!(s_ab < s_aa) ok
    703 (strcmp("ab", s_aa) > 0) ok
     703(cmp("ab", s_aa) > 0) ok
    704704!("ab" == s_aa) ok
    705705("ab" != s_aa) ok
     
    708708!("ab" <= s_aa) ok
    709709!("ab" < s_aa) ok
    710 (strcmp(s_ab, "aa") > 0) ok
     710(cmp(s_ab, "aa") > 0) ok
    711711!(s_ab == "aa") ok
    712712(s_ab != "aa") ok
     
    715715!(s_ab <= "aa") ok
    716716!(s_ab < "aa") ok
    717 (strcmp(s_ba, s_bb) < 0) ok
     717(cmp(s_ba, s_bb) < 0) ok
    718718!(s_ba == s_bb) ok
    719719(s_ba != s_bb) ok
     
    722722(s_ba <= s_bb) ok
    723723(s_ba < s_bb) ok
    724 (strcmp("ba", s_bb) < 0) ok
     724(cmp("ba", s_bb) < 0) ok
    725725!("ba" == s_bb) ok
    726726("ba" != s_bb) ok
     
    729729("ba" <= s_bb) ok
    730730("ba" < s_bb) ok
    731 (strcmp(s_ba, "bb") < 0) ok
     731(cmp(s_ba, "bb") < 0) ok
    732732!(s_ba == "bb") ok
    733733(s_ba != "bb") ok
     
    736736(s_ba <= "bb") ok
    737737(s_ba < "bb") ok
    738 (strcmp(s_bb, s_ba) > 0) ok
     738(cmp(s_bb, s_ba) > 0) ok
    739739!(s_bb == s_ba) ok
    740740(s_bb != s_ba) ok
     
    743743!(s_bb <= s_ba) ok
    744744!(s_bb < s_ba) ok
    745 (strcmp("bb", s_ba) > 0) ok
     745(cmp("bb", s_ba) > 0) ok
    746746!("bb" == s_ba) ok
    747747("bb" != s_ba) ok
     
    750750!("bb" <= s_ba) ok
    751751!("bb" < s_ba) ok
    752 (strcmp(s_bb, "ba") > 0) ok
     752(cmp(s_bb, "ba") > 0) ok
    753753!(s_bb == "ba") ok
    754754(s_bb != "ba") ok
     
    757757!(s_bb <= "ba") ok
    758758!(s_bb < "ba") ok
    759 (strcmp(s_aa, s_b) < 0) ok
     759(cmp(s_aa, s_b) < 0) ok
    760760!(s_aa == s_b) ok
    761761(s_aa != s_b) ok
     
    764764(s_aa <= s_b) ok
    765765(s_aa < s_b) ok
    766 (strcmp("aa", s_b) < 0) ok
     766(cmp("aa", s_b) < 0) ok
    767767!("aa" == s_b) ok
    768768("aa" != s_b) ok
     
    771771("aa" <= s_b) ok
    772772("aa" < s_b) ok
    773 (strcmp(s_aa, "b") < 0) ok
     773(cmp(s_aa, "b") < 0) ok
    774774!(s_aa == "b") ok
    775775(s_aa != "b") ok
     
    778778(s_aa <= "b") ok
    779779(s_aa < "b") ok
    780 (strcmp(s_b, s_aa) > 0) ok
     780(cmp(s_b, s_aa) > 0) ok
    781781!(s_b == s_aa) ok
    782782(s_b != s_aa) ok
     
    785785!(s_b <= s_aa) ok
    786786!(s_b < s_aa) ok
    787 (strcmp("b", s_aa) > 0) ok
     787(cmp("b", s_aa) > 0) ok
    788788!("b" == s_aa) ok
    789789("b" != s_aa) ok
     
    792792!("b" <= s_aa) ok
    793793!("b" < s_aa) ok
    794 (strcmp(s_b, "aa") > 0) ok
     794(cmp(s_b, "aa") > 0) ok
    795795!(s_b == "aa") ok
    796796(s_b != "aa") ok
  • tests/collections/.expect/string-istream-manip.txt

    rf988834 r59c8dff  
    696913 wwwwwwww
    707014 cccc
    71 15
     7115 q
    72721 yyyyyyyyyyyyyyyyyyyy
    73732 abcxxx
     
    848413 wwwwwwww
    858514 cccc
    86 15
     8615 q
  • tests/collections/string-api-coverage.cfa

    rf988834 r59c8dff  
    5151    sout | (s == "hello") | (s == "world");
    5252    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"   );
    6161
    6262
     
    6666    //
    6767    {
    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
    7370
    7471        string b2 = s;
    7572        sout | b2; // hello
    76 
    77         string b2x = { s, 4 };
    78         sout | b2x; // hell
    7973
    8074        // todo: a plain string &
     
    9488        b4 = s_constref;
    9589        sout | b4;  // world
    96 
    97         string b5 = 'Q';
    98         sout | b5; // Q
    99 
    100 
    10190    }
    10291                                            assertWellFormedHandleList( 10 );
    103     //
    104     // Assignments
    105     //
    106     {
    107         string b = "xxx";
    108 
    109         b = "1234567";
    110         sout | b; // 1234567
    111 
    112         b = "xxx";
    113         b = s;
    114         sout | b; // hello
    115        
    116         b = "xxx";
    117         b = 'Q';
    118         sout | b; // Q
    119        
    120         b = "xxx";
    121         assign( b, "1234567", 3 );
    122         sout | b; // 123
    123 
    124         b = "xxx";
    125         assign( b, s, 4 );
    126         sout | b; // hell
    127 
    128         b = "xxx";
    129         strcpy(b, "1234567");
    130         sout | b; // 1234567
    131 
    132         b = "xxx";
    133         strcpy(b, s);
    134         sout | b; // hello
    135        
    136         b = "xxx";
    137         strncpy( b, "1234567", 3 );
    138         sout | b; // 123
    139 
    140         b = "xxx";
    141         strncpy( b, s, 4 );
    142         sout | b; // hell
    143     }
    144                                             assertWellFormedHandleList( 10 );
    145 
    146 
    14792
    14893    sout | size(s); // 5
     
    181126    sout | sx; // bye, friend
    182127
    183     sx = "o";
    184     strcat( sx, s );
    185     sout | sx; // ohello
    186 
    187     sx = "o";
    188     append( sx, s, 4 );
    189     sout | sx; // ohell
    190 
    191     sx = "o";
    192     strncat( sx, s, 4 );
    193     sout | sx; // ohell
    194 
    195     sx = "o";
    196     strcat( sx, "mydarling" );
    197     sout | sx; // omydarling
    198 
    199     sx = "o";
    200     append( sx, "mydarling", 2 );
    201     sout | sx; // omy
    202 
    203     sx = "o";
    204     strncat( sx, "mydarling", 2 );
    205     sout | sx; // omy
    206 
    207128    //
    208129    // repetition
    209130    //
    210 
    211     sx = s;
    212     sx *= 4;
    213     sout | sx; // hellohellohellohello
    214 
    215131    sx = s * 3;
    216132    sout | sx; // hellohellohello
     
    226142    //
    227143
    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    //...
    236145
    237146    //
     
    335244        | find( alphabet        , "def")  // 3
    336245        | find( alphabet( 0, 26), "def")  // 3
    337         | find( alphabet( 2, 24), "def")  // 1
    338         | find( alphabet( 3, 23), "def")  // 0
    339         | find( alphabet( 4, 22), "def")  // 22, not found
    340         | find( alphabet( 4, 22),  "ef")  // 0
     246        | 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
    341250        | find( alphabet( 0,  6), "def")  // 3
    342251        | find( alphabet( 0,  5), "def")  // 5, not found
     
    346255        | includes( alphabet        , "def")  // true
    347256        | includes( alphabet( 0, 26), "def")  // true
    348         | includes( alphabet( 2, 24), "def")  // true
    349         | includes( alphabet( 3, 23), "def")  // true
    350         | includes( alphabet( 4, 22), "def")  // false
    351         | includes( alphabet( 4, 22),  "ef")  // true
     257        | 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
    352261        | includes( alphabet( 0,  6), "def")  // true
    353262        | includes( alphabet( 0,  5), "def")  // false
     
    357266        | startsWith( alphabet        , "abc")  // true
    358267        | startsWith( alphabet( 0, 26), "abc")  // true
    359         | startsWith( alphabet( 1, 25), "abc")  // false
    360         | startsWith( alphabet( 1, 25),  "bc")  // true
     268        | startsWith( alphabet( 1, 26), "abc")  // false
     269        | startsWith( alphabet( 1, 26),  "bc")  // true
    361270        | startsWith( alphabet( 0, 26), "abc")  // true
    362271        | startsWith( alphabet( 0,  4), "abc")  // true
     
    372281        | endsWith( alphabet( 0, 25), "xy" )  // true
    373282        | endsWith( alphabet( 0, 26), "xyz")  // true
    374         | endsWith( alphabet(23,  3), "xyz")  // true
    375         | endsWith( alphabet(24,  2), "xyz")  // false
    376         | endsWith( alphabet(24,  2),  "yz")  // true
     283        | endsWith( alphabet(23, 26), "xyz")  // true
     284        | endsWith( alphabet(24, 26), "xyz")  // false
     285        | endsWith( alphabet(24, 26),  "yz")  // true
    377286        | endsWith( alphabet        , "abc"); // false
    378287
  • tests/collections/string-compare.cfa

    rf988834 r59c8dff  
    33
    44#define test_eq_(l, r) \
    5     chk( (strcmp(l, r) == 0) ) \
     5    chk( (cmp(l, r) == 0) ) \
    66    chk(  (l == r) ) \
    77    chk( !(l != r) ) \
     
    1717
    1818#define test_lt_(l, r) \
    19     chk( (strcmp(l, r) < 0) ) \
     19    chk( (cmp(l, r) < 0) ) \
    2020    chk( !(l == r) ) \
    2121    chk(  (l != r) ) \
     
    2626
    2727#define test_gt_(l, r) \
    28     chk( (strcmp(l, r) > 0) ) \
     28    chk( (cmp(l, r) > 0) ) \
    2929    chk( !(l == r) ) \
    3030    chk(  (l != r) ) \
  • tests/collections/string-overwrite.cfa

    rf988834 r59c8dff  
    99MS = modifier start
    1010ME = modifier end
    11 ML = modifier length
    1211WS = witness start
    1312WE = witness end
    14 WL = witness length
    1513
    1614The test does:
     
    7371
    7472
    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;
     73void showOneReplacement(string & s, int ms, int me, int ws, int we, const char* replaceWith) {
    7974
    8075    assert( ms >= 0 && ms <= me && me <= size(s) );
    8176    assert( ws >= 0 && ws <= we && we <= size(s) );
    8277
    83     string mod = s(ms, ml)`shareEdits;
    84     string wit = s(ws, wl)`shareEdits;
     78    string mod = s(ms, me)`shareEdits;
     79    string wit = s(ws, we)`shareEdits;
    8580
    8681    string modOld = mod;
     
    123118void runReplaceCases() {
    124119    char * alphabetTemplate = "abcdefghijklmnopqrstuvwxyz";
    125     struct { int ms; int ml; 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 string
    166         { 10,  4, 12,  2, ""     , ""       },  // ditto
    167         { 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 watching
    172         { 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, ""     , ""       },
    231226    };
    232227    for ( i; sizeof(cases)/sizeof(cases[0]) ) {
    233228        sout | "------------------------------------------------------------------------" | cases[i].label;
    234229        string replaceIn = alphabetTemplate;
    235         showOneReplacement( replaceIn, cases[i].ms, cases[i].ml, 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 );
    236231    }
    237232}
     
    249244    string s = "abcdefghijklmnopqrstuvwxyz";
    250245
    251     s(5,5) = "qqqqq";  // start=5, end=10, len=5
    252 
    253     sout | s;
    254 
    255 
    256     s(5,0) = "-----";  // start=5, end=5, len=0
     246    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
    257252
    258253    sout | s;
  • tests/concurrency/examples/quickSort.cfa

    rf988834 r59c8dff  
    1111// Created On       : Wed Dec  6 12:15:52 2017
    1212// Last Modified By : Peter A. Buhr
    13 // Last Modified On : Mon Jan  1 12:07:59 2024
    14 // Update Count     : 188
     13// Last Modified On : Wed Feb 12 18:24:47 2020
     14// Update Count     : 177
    1515//
    1616
    17 #include <fstream.hfa>                                                                  // sin/sout
    18 #include <stdlib.hfa>                                                                   // convert
     17#include <fstream.hfa>
     18#include <stdlib.hfa>
     19#include <kernel.hfa>
    1920#include <thread.hfa>
    20 #include <math.hfa>                                                                             // sqrt
    2121#include <string.h>                                                                             // strcmp
    2222
     
    8282} // main
    8383
    84 // convert(...) throws out_of_range or invalid_argument
    85 ExceptionDecl( cmd_error );
     84
     85bool 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
     92void 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
    8697
    8798int 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;
    93102
    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
    96107                        choose ( argc ) {
    97108                          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 );
    100110                                fallthrough;
    101111                          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 );
    106113                        } // choose
    107114                } else {                                                                                // sort file
    108115                        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 );
    129121                                } // if
    130122                                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
    134129                        } // choose
    135130                } // 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
    141133
    142134        enum { ValuesPerLine = 22 };                                            // number of values printed per line
    143135
    144         sortedfile | nlOff;                                                                     // turn off auto newline
    145 
    146         if ( size == -1 ) {                                                                     // generate output ?
     136        if ( &unsortedfile ) {                                                          // generate output ?
    147137                for () {
    148138                        unsortedfile | size;                                            // read number of elements in the list
    149139                  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
    152141                        for ( counter; size ) {                                         // read unsorted numbers
    153142                                unsortedfile | values[counter];
     
    157146                        } // for
    158147                        sortedfile | nl;
    159 
    160148                        if ( size > 0 ) {                                                       // values to sort ?
    161149                                Quicksort QS = { values, size - 1, 0 }; // sort values
     
    170158                        delete( values );
    171159                } // 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 {
    174163                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 stack
    176164
     165                int * values = alloc( size );                                   // values to be sorted, too large to put on stack
    177166                for ( counter; size ) {                                                 // generate unsorted numbers
    178167                        values[counter] = size - counter;                       // descending values
    179168                } // 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] );
    184171                } // for
    185172                {
  • tests/exceptions/hotpotato.cfa

    rf988834 r59c8dff  
    55
    66struct Potato {
    7         PRNG & prng;
    8         unsigned int deadline;                                                          // when timer goes off
    9         unsigned int timer;                                                                     // up counter to deadline
     7        PRNG & prng;
     8        unsigned int deadline;                                                          // when timer goes off
     9        unsigned int timer;                                                                     // up counter to deadline
    1010}; // Potato
    1111
     
    1616        &potato.prng = &prng;
    1717        reset( potato, maxTicks );
    18                 } // Potato
     18} // Potato
    1919
    2020coroutine Player {
    21         PRNG & prng;
    22         int id;                                                                                         // player identity
    23         Potato & potato;                                                                        // potato being tossed
    24         Player * partner[2];                                                            // left and right player
     21        PRNG & prng;
     22        int id;                                                                                         // player identity
     23        Potato & potato;                                                                        // potato being tossed
     24        Player * partner[2];                                                            // left and right player
    2525}; // Player
    2626
     
    2929        player.id = id;
    3030        &player.potato = &potato;
    31                 } // Player
     31} // Player
    3232
    3333Player & umpire;
     
    3939
    4040void reset( Potato & potato, unsigned int maxTicks ) with(potato) {
    41         if ( maxTicks < 2 ) abort( "Hot Potato initialized with less than 2 ticks" ); // optional
     41  if ( maxTicks < 2 ) abort( "Hot Potato initialized with less than 2 ticks" ); // optional
    4242        deadline = prng( prng, 1, maxTicks );
    4343        timer = 0;
     
    6060enum { LEFT = 0, RIGHT = 1 };
    6161
    62 static void vote( Player & player, Election & election ) { // cause partner to vote
    63         resumeAt( player, election );
     62static void vote( Player & player, Election & election ) {                                      // cause partner to vote
     63    resumeAt( player, election );
    6464        resume( player );
    6565} // vote
     
    7676
    7777void main( Player & player ) with(player) {
    78         suspend;                                                                                        // return immediately after establishing starter
     78    suspend;                                                                    // return immediately after establishing starter
    7979        try {
    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
     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
    9494        } catchResume( Terminate * v ) {
    9595                v->victim->partner[LEFT]->partner[RIGHT] = v->victim->partner[RIGHT]; // unlink node
    9696                v->victim->partner[RIGHT]->partner[LEFT] = v->victim->partner[LEFT];
    97                 delete( v->victim );
     97        delete( v->victim );
    9898                reset( potato );
    9999                sout | "U " | nonl;                                                             // start new game
     
    102102                sout | "election";
    103103                sout | " -> " | id | nonl;
    104                 if ( id > getId( umpire ) ) &umpire = &player;  // set umpire to highest id so far
     104                if ( id > getId( umpire ) ) &umpire = &player; // set umpire to highest id so far
    105105                vote( *partner[RIGHT], *election );
    106106        } catchResume ( Explode * ) {
    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
     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
    118118} // main
    119119
     
    151151                  case 1: ;                                                                             // defaults
    152152                  default:                                                                              // too many arguments
    153                           throw ExceptionInst( cmd_error );
     153                        throw ExceptionInst( cmd_error );
    154154                } // choose
    155155        } catch( exception_t * ) {                                                      // catch any
    156156                exit | "Usage: " | argv[0]
    157                         | " [ games (>=0) | 'd' (default " | DefaultGames
    158                         | ") [ players (>=2) | 'd' (random " | MinNoPlayers | "-" | MaxNoPlayers
    159                         | ") [ seed (>0) | 'd' (random) ] ] ]";
     157                         | " [ games (>=0) | 'd' (default " | DefaultGames
     158                         | ") [ players (>=2) | 'd' (random " | MinNoPlayers | "-" | MaxNoPlayers
     159                         | ") [ seed (>0) | 'd' (random) ] ] ]";
    160160        } // try
    161161        sout | numGames | numPlayers | seed;
  • tests/exceptions/hotpotato_checked.cfa

    rf988834 r59c8dff  
    55
    66struct Potato {
    7         PRNG & prng;
    8         unsigned int deadline;                                                          // when timer goes off
    9         unsigned int timer;                                                                     // up counter to deadline
     7        PRNG & prng;
     8        unsigned int deadline;                                                          // when timer goes off
     9        unsigned int timer;                                                                     // up counter to deadline
    1010}; // Potato
    1111
     
    1616        &potato.prng = &prng;
    1717        reset( potato, maxTicks );
    18                 } // Potato
     18} // Potato
    1919
    2020coroutine Player {
    21         PRNG & prng;
    22         int id;                                                                                         // player identity
    23         Potato & potato;                                                                        // potato being tossed
    24         Player * partner[2];                                                            // left and right player
     21        PRNG & prng;
     22        int id;                                                                                         // player identity
     23        Potato & potato;                                                                        // potato being tossed
     24        Player * partner[2];                                                            // left and right player
    2525}; // Player
    2626
     
    2929        player.id = id;
    3030        &player.potato = &potato;
    31                 } // Player
     31} // Player
    3232
    3333Player & umpire;
     
    3939
    4040void reset( Potato & potato, unsigned int maxTicks ) with(potato) {
    41         if ( maxTicks < 2 ) abort( "Hot Potato initialized with less than 2 ticks" ); // optional
     41  if ( maxTicks < 2 ) abort( "Hot Potato initialized with less than 2 ticks" ); // optional
    4242        deadline = prng( prng, 1, maxTicks );
    4343        timer = 0;
     
    6666static void terminate( Player & player ) {                              // resume umpire
    6767        resume( player );
    68         checked_poll();
    69         sout | "THIS SHOULD NOT BE REACHED";
     68    checked_poll();
     69    sout | "THIS SHOULD NOT BE REACHED";
    7070} // terminate
    7171
     
    7474        partner[RIGHT] = &rp;
    7575        resume( player );                                                                       // establish main as starter for termination
    76         checked_poll();
     76    checked_poll();
    7777} // init
    7878
     
    8282
    8383void toss( Player & player ) {                                                  // tossed the potato
    84         resume( player );
     84    resume( player );
    8585        checked_poll();
    8686} // toss
     
    8888void main( Player & player ) with(player) {
    8989        try {
    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();
     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();
    108108        } catchResume( Terminate * v ) {
    109109                v->victim->partner[LEFT]->partner[RIGHT] = v->victim->partner[RIGHT]; // unlink node
    110110                v->victim->partner[RIGHT]->partner[LEFT] = v->victim->partner[LEFT];
    111                 delete( v->victim );
     111        delete( v->victim );
    112112                reset( potato );
    113113                sout | "U " | nonl;                                                             // start new game
     
    116116                sout | "election";
    117117                sout | " -> " | id | nonl;
    118                 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
     118                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
    121121                vote( *partner[RIGHT] );
    122                 enable_ehm();                                                                   // enable after vote
     122        enable_ehm();               // enable after vote
    123123        } catchResume( Explode * ) {
    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
     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
    139139} // main
    140140
     
    172172                  case 1: ;                                                                             // defaults
    173173                  default:                                                                              // too many arguments
    174                           throw ExceptionInst( cmd_error );
     174                        throw ExceptionInst( cmd_error );
    175175                } // choose
    176176        } catch( exception_t * ) {                                                      // catch any
    177177                exit | "Usage: " | argv[0]
    178                         | " [ games (>=0) | 'd' (default " | DefaultGames
    179                         | ") [ players (>=2) | 'd' (random " | MinNoPlayers | "-" | MaxNoPlayers
    180                         | ") [ seed (>0) | 'd' (random) ] ] ]";
     178                         | " [ games (>=0) | 'd' (default " | DefaultGames
     179                         | ") [ players (>=2) | 'd' (random " | MinNoPlayers | "-" | MaxNoPlayers
     180                         | ") [ seed (>0) | 'd' (random) ] ] ]";
    181181        } // try
    182182        sout | numGames | numPlayers | seed;
  • tests/io/.expect/manipulatorsInput.arm64.txt

    rf988834 r59c8dff  
    202014 rc=1, cccc
    212115 rc=0, q
    22 16 get this line
    23 17 @# this line 1)-{}
    24 18 abc
    25 19 abc 
    26 20  d d
    27 
    28 d
    29 21              ZC44%
    30221 yyyyyyyyyyyyyyyyyyyy
    31232 abcxxx
     
    433514 cccc
    443615
    45 16 get this line
    46 17 @# this line 1)-{}
    47 18 abc
    48 19 abc 
    49 20 d d
    50 
    51 d
    52 21              ZC44%
    5337a
    5438a
  • tests/io/.expect/manipulatorsInput.x64.txt

    rf988834 r59c8dff  
    202014 rc=1, cccc
    212115 rc=0, q
    22 16 get this line
    23 17 @# this line 1)-{}
    24 18 abc
    25 19 abc 
    26 20  d d
    27 
    28 d
    29 21              ZC44%
    30221 yyyyyyyyyyyyyyyyyyyy
    31232 abcxxx
     
    433514 cccc
    443615
    45 16 get this line
    46 17 @# this line 1)-{}
    47 18 abc
    48 19 abc 
    49 20 d d
    50 
    51 d
    52 21              ZC44%
    5337a
    5438a
  • tests/io/.expect/manipulatorsInput.x86.txt

    rf988834 r59c8dff  
    202014 rc=1, cccc
    212115 rc=0, q
    22 16 get this line
    23 17 @# this line 1)-{}
    24 18 abc
    25 19 abc 
    26 20  d d
    27 
    28 d
    29 21              ZC44%
    30221 yyyyyyyyyyyyyyyyyyyy
    31232 abcxxx
     
    433514 cccc
    443615
    45 16 get this line
    46 17 @# this line 1)-{}
    47 18 abc
    48 19 abc 
    49 20 d d
    50 
    51 d
    52 21              ZC44%
    5337a
    5438a
  • tests/io/.in/manipulatorsInput.txt

    rf988834 r59c8dff  
    1010aaaaaaaaxxxxxxxxaabbccbbdddwwwbbbbbbbbwwwwwwwwaaaaaaaawwwwwwww
    1111uuuuuccccuuuuu
    12 get this line
    13 @# this line 1)-{}%
    14 "abc"
    15 'abc  '
    16 { d d
    17 
    18 d }
    19 X               ZC44%Y
    2012abc
    2113cccccb
     
    2517aaaaaaaaxxxxxxxxaabbccbbdddwwwbbbbbbbbwwwwwwwwaaaaaaaawwwwwwww
    2618uuuuuccccuuuuu
    27 get this line
    28 @# this line 1)-{}%
    29 "abc"
    30 'abc  '
    31 { d d
    32 
    33 d }
    34 X               ZC44%Y
    3519ab
    36200xff 017 15-15
  • tests/io/manipulatorsInput.cfa

    rf988834 r59c8dff  
    77// Created On       : Sat Jun  8 17:58:54 2019
    88// Last Modified By : Peter A. Buhr
    9 // Last Modified On : Wed Jan  3 11:15:04 2024
    10 // Update Count     : 103
     9// Last Modified On : Sat Sep  2 14:27:46 2023
     10// Update Count     : 65
    1111//
    1212
     
    7777                s[0] = 'q'; s[1] = '\0'; rc = 99;
    7878                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");
    9281        }
    9382        {
     
    113102                s[0] = 'q'; s[1] = '\0';
    114103                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 */
    125108        {
    126109                char c;
Note: See TracChangeset for help on using the changeset viewer.