Term input/output
Author: Daniel Diaz
Keywords: GNU Prolog, manual, Prolog, compiler, constraints, finite domains

### 8.14 Term input/output

- read_term/3, read_term/2, read/2, read/1
- read_atom/2, read_atom/1, read_integer/2, read_integer/1,
  read_number/2, read_number/1
- read_token/2, read_token/1
- syntax_error_info/4
- last_read_start_line_column/2
- write_term/3, write_term/2, write/2, write/1, writeq/2, writeq/1,
  write_canonical/2, write_canonical/1, display/2, display/1, print/2,
  print/1
- format/3, format/2
- portray_clause/2, portray_clause/1
- get_print_stream/1
- op/3
- current_op/3
- char_conversion/2
- current_char_conversion/2

These built-in predicates enable a Prolog term to be input from or output to a text stream. The atom end_of_file is returned as term to indicate the end-of-file. The syntax of such terms can also be altered by changing the operators (section 8.14.10), and making some characters equivalent to others (section 8.14.12) if the char_conversion Prolog flag is on (section 8.22.1). Double quoted tokens will be returned as an atom or a character list or a character code list depending on the value of the double_quotes Prolog flag (section 8.22.1). Similarly, back quoted tokens are returned depending on the value of the back_quotes Prolog flag.

#### 8.14.1 read_term/3, read_term/2, read/2, read/1

Templates

  read_term(+stream_or_alias, ?term, +read_option_list)
  read_term(?term, +read_option_list)
  read(+stream_or_alias, ?term)
  read(?term)

Description

read_term(SorA, Term, Options) is true if Term unifies with the next term read from the stream associated with the stream-term or alias SorA according to the options given by Options.

Read options: Options is a list of read options. If this list contains contradictory options, the rightmost option is the one which applies. Possible options are:

- variables(VL): VL is unified with the list of all variables of the input term, in left-to-right traversal order. Anonymous variables are included in the list VL.
- variable_names(VNL): VNL is unified with the list of pairs Name = Var where Var is a named variable of the term and Name is the atom associated with the name of Var. Anonymous variables are not included in the list VNL. The pairs appear in left-to-right traversal order of their Var in the term.
- singletons(SL): SL is unified with the list of pairs Name = Var where Var is a named variable which occurs only once in the term and Name is the atom associated to the name of Var. Anonymous variables are not included in the list SL.
- syntax_error(error/warning/fail): specifies the effect of a syntax error:
  - error: a syntax_error is raised.
  - warning: a warning message is displayed and the predicate fails.
  - fail: the predicate quietly fails.

  The default value is the value of the syntax_error Prolog flag (section 8.22.1).

- end_of_term(dot/eof): specifies the end-of-term delimiter: dot is the classical full-stop delimiter (a dot followed with a layout character), eof is the end-of-file delimiter. This option is useful for predicates like read_term_from_atom/3 (section 8.15.1) to avoid to add a terminal dot at the end of the atom. The default value is dot.

read(SorA, Term) is equivalent to read_term(SorA, Term, []).

read_term/2 and read/1 apply to the current input stream.

Errors

SorA is a variable |  | instantiation_error
Options is a partial list or a list with an element E which is a variable |  | instantiation_error
SorA is neither a variable nor a stream-term or alias |  | domain_error(stream_or_alias, SorA)
Options is neither a partial list nor a list |  | type_error(list, Options)
an element E of the Options list is neither a variable nor a valid read option |  | domain_error(read_option, E)
SorA is not associated with an open stream |  | existence_error(stream, SorA)
SorA is an output stream |  | permission_error(input, stream, SorA)
SorA is associated with a binary stream |  | permission_error(input, binary_stream, SorA)
SorA has stream properties end_of_stream(past) and eof_action(error) |  | permission_error(input, past_end_of_stream, SorA)
a syntax error occurs and the value of the syntax_error Prolog flag is error (section 8.22.1) |  | syntax_error(atom explaining the error)

Portability

ISO predicates. The ISO reference raises a representation_error(Flag) where Flag is max_arity, max_integer, or min_integer when the read term breaches an implementation defined limit specified by Flag. GNU Prolog detects neither min_integer nor max_integer violation and treats a max_arity violation as a syntax error. The read options syntax_error and end_of_term are GNU Prolog extensions.

#### 8.14.2 read_atom/2, read_atom/1, read_integer/2, read_integer/1,
read_number/2, read_number/1

Templates

  read_atom(+stream_or_alias, ?atom)
  read_atom(?atom)
  read_integer(+stream_or_alias, ?integer)
  read_integer(?integer)
  read_number(+stream_or_alias, ?number)
  read_number(?number)

Description

read_atom(SorA, Atom) succeeds if Atom unifies with the next atom read from the stream associated with the stream-term or alias SorA.

read_integer(SorA, Integer) succeeds if Integer unifies with the next integer read from the stream associated with the stream-term or alias SorA.

read_number(SorA, Number) succeeds if Number unifies with the next number (integer or floating point number) read from the stream associated with the stream-term or alias SorA.

read_atom/1, read_integer/1 and read_number/1 apply to the current input stream.

Errors

SorA is a variable |  | instantiation_error
Atom is neither a variable nor an atom |  | type_error(atom, Atom)
Integer is neither a variable nor an integer |  | type_error(integer, Integer)
Number is neither a variable nor a number |  | type_error(number, Number)
SorA is neither a variable nor a stream-term or alias |  | domain_error(stream_or_alias, SorA)
SorA is not associated with an open stream |  | existence_error(stream, SorA)
SorA is an output stream |  | permission_error(input, stream, SorA)
SorA is associated with a binary stream |  | permission_error(input, binary_stream, SorA)
SorA has stream properties end_of_stream(past) and eof_action(error) |  | permission_error(input, past_end_of_stream, SorA)
a syntax error occurs and the value of the syntax_error Prolog flag is error (section 8.22.1) |  | syntax_error(atom explaining the error)

Portability

GNU Prolog predicates.

#### 8.14.3 read_token/2, read_token/1

Templates

  read_token(+stream_or_alias, ?nonvar)
  read_token(?nonvar)

Description

read_token(SorA, Token) succeeds if Token unifies with the encoding of the next Prolog token read from the stream associated with stream-term or alias SorA.

Token encoding:

- var(A): a variable is read whose name is the atom A.
- an atom A: an atom A is read.
- integer N: an integer N is read.
- floating point number N: a floating point number N is read.
- string(A): a string (double quoted item) is read whose characters forms the atom A.
- punct(P): a punctuation character P is read (P is a one-character atom in ()[]{|}, the atom full_stop or the atom end_of_file).
- back_quotes(A): a back quoted item is read whose characters forms the atom A.
- extended(A): an extended character A (an atom) is read.

As for read_term/3, the behavior of read_token/2 can be affected by some Prolog flags (section 8.14).

read_token/1 applies to the current input stream.

Errors

SorA is a variable |  | instantiation_error
SorA is neither a variable nor a stream-term or alias |  | domain_error(stream_or_alias, SorA)
SorA is not associated with an open stream |  | existence_error(stream, SorA)
SorA is an output stream |  | permission_error(input, stream, SorA)
SorA is associated with a binary stream |  | permission_error(input, binary_stream, SorA)
SorA has stream properties end_of_stream(past) and eof_action(error) |  | permission_error(input, past_end_of_stream, SorA)
a syntax error occurs and the value of the syntax_error Prolog flag is error (section 8.22.1) |  | syntax_error(atom explaining the error)

Portability

GNU Prolog predicates.

#### 8.14.4 syntax_error_info/4

Templates

  syntax_error_info(?atom, ?integer, ?integer, ?atom)

Description

syntax_error_info(FileName, Line, Column, Error) returns the information associated with the last syntax error. Line is the line number of the error, Column is the column number of the error and Error is an atom explaining the error.

Errors

FileName is neither a variable nor an atom |  | type_error(atom, FileName)
Line is neither a variable nor an integer |  | type_error(integer, Line)
Column is neither a variable nor an integer |  | type_error(integer, Column)
Error is neither a variable nor an atom |  | type_error(atom, Error)

Portability

GNU Prolog predicate.

#### 8.14.5 last_read_start_line_column/2

Templates

  last_read_start_line_column(?integer, ?integer)

Description

last_read_start_line_column(Line, Column) unifies Line and Column with the line number and the column number associated with the start of the last read predicate. This predicate can be used after calling one of the following predicates: read_term/3, read_term/2, read/2, read/1 (section 8.14.1), read_atom/2, read_atom/1, read_integer/2, read_integer/1, read_number/2, read_number/1 (section 8.14.2) or read_token/2, read_token/1 (section 8.14.3).

Errors

Line is neither a variable nor an integer |  | type_error(integer, Line)
Column is neither a variable nor an integer |  | type_error(integer, Column)

Portability

GNU Prolog predicate.

#### 8.14.6 write_term/3, write_term/2, write/2, write/1, writeq/2, writeq/1,
write_canonical/2, write_canonical/1, display/2, display/1, print/2,
print/1

Templates

  write_term(+stream_or_alias, ?term, +write_option_list)
  write_term(?term, +write_option_list)
  write(+stream_or_alias, ?term)
  write(?term)
  writeq(+stream_or_alias, ?term)
  writeq(?term)
  write_canonical(+stream_or_alias, ?term)
  write_canonical(?term)
  display(+stream_or_alias, ?term)
  display(?term)
  print(+stream_or_alias, ?term)
  print(?term)

Description

write_term(SorA, Term, Options) writes Term to the stream associated with the stream-term or alias SorA according to the options given by Options.

Write options: Options is a list of write options. If this list contains contradictory options, the rightmost option is the one which applies. Possible options are:

- quoted(true/false): if true each atom and functor is quoted if this would be necessary for the term to be input by read_term/3. If false no extra quotes are written. The default value is false.
- ignore_ops(true/false): if true each compound term is output in functional notation (neither operator notation nor list notation is used). If false operator and list notations are used. The default value is false.
- numbervars(true/false): if true a term of the form ’$VAR’(N), where N is an integer, is output as a variable name (see below). If false such a term is output normally (according to the other options). The default value is false.
- namevars(true/false): if true a term of the form ’$VARNAME’(Name), where Name is an atom respecting the syntax of variable names, is output as a variable name (see below). If false such a term is output normally (according to the other options). The default value is false.
- variable_names(VNL): VNL is a list of pairs Name = Var where Var is a variable and Name is the atom associated with the name of Var. Each variable Var is written as the atom Name (with quoted(false)) iff a term Name = Var is an element of the list VNL. If several pairs exist for the same variable name the first one applies.
- space_args(true/false): if true an extra space character is emitted after each comma separating the arguments of a compound term in functional notation or of a list. If false no extra space is emitted. The default value is false.
- portrayed(true/false): if true and if there exists a predicate portray/1, write_term/3 acts as follows: if Term is a variable it is simply written. If Term is non-variable then it is passed to portray/1. If this succeeds then it is assumed that Term has been output. Otherwise write_term/3 outputs the principal functor of Term (Term itself if it is atomic) according to other options and recursively calls portray/1 on the components of Term (if it is a compound term). With ignore_ops(false) a list is first passed to portray/1 and only if this call fails each element of the list is passed to portray/1 (thus every sub-list is not passed). The default value is false.
- max_depth(N): controls the depth of output for compound terms. N is an integer specifying the depth. The output of a term whose depth is greater than N gives rise to the output of ... (3 dots). By default there is no depth limit.
- priority(N): specifies the starting priority to output the term. This option controls if Term should be enclosed in brackets. N is a positive integer ≤ 1200. By default N = 1200.

Variable numbering: when the numbervars(true) option is passed to write_term/3 any term of the form ’$VAR’(N) where N is an integer is output as a variable name consisting of a capital letter possibly followed by an integer. The capital letter is the (I+1)th letter of the alphabet and the integer is J, where I = N mod 26 and J = N // 26. The integer J is omitted if it is zero. For example:

  ’$VAR’(0) |  | is written as A
  ’$VAR’(1) |  | is written as B
  ...
  ’$VAR’(25) |  | is written as Z
  ’$VAR’(26) |  | is written as A1
  ’$VAR’(27) |  | is written as B1

Variable naming: when the namevars(true) option is passed to write_term/3 any term of the form ’$VARNAME’(Name) where Name is an atom is output as a variable name consisting of the characters Name. For example: ’$VARNAME’(’A’) is written as A (even in the presence of the quoted(true) option).

write(SorA, Term) is equivalent to write_term(SorA, Term, [numbervars(true),
namevars(true)]).

writeq(SorA, Term) is equivalent to write_term(SorA, Term, [quoted(true),
numbervars(true), namevars(true)]).

write_canonical(SorA, Term) is equivalent to write_term(SorA, Term, [quoted(true),
ignore_ops(true), numbervars(false), namevars(false)]).

display(SorA, Term) is equivalent to write_term(SorA, Term, [ignore_ops(true),
numbervars(false), namevars(false)]).

print(SorA, Term) is equivalent to write_term(SorA, Term, [numbervars(false),
portrayed(true)]).

write_term/2, write/1, writeq/1, write_canonical/1, display/1 and print/1 apply to the current output stream.

Errors

SorA is a variable |  | instantiation_error
Options is a partial list or a list with an element E which is a variable |  | instantiation_error
Options is neither a partial list nor a list |  | type_error(list, Options)
SorA is neither a variable nor a stream-term or alias |  | domain_error(stream_or_alias, SorA)
an element E of the Options list is neither a variable nor a valid write-option |  | domain_error(write_option, E)
SorA is not associated with an open stream |  | existence_error(stream, SorA)
SorA is an input stream |  | permission_error(output, stream, SorA)
SorA is associated with a binary stream |  | permission_error(output, binary_stream, SorA)

Portability

ISO predicates except display/1-2 and print/1-2 that are GNU Prolog predicates. namevars, variable_names space_args, portrayed, max_depth and priority options are GNU Prolog extensions.

#### 8.14.7 format/3, format/2

Templates

  format(+stream_or_alias, +character_code_list_or_atom, +list)
  format(+character_code_list_or_atom, +list)

Description

format(SorA, Format, Arguments) writes the Format string replacing each format control sequence F by the corresponding element of Arguments (formatted according to F) to the stream associated with the stream-term or alias SorA.

Format control sequences: the general format of a control sequence is ’~NC’. The character C determines the type of the control sequence. N is an optional numeric argument. An alternative form of N is ’*’. ’*’ implies that the next argument Arg in Arguments should be used as a numeric argument in the control sequence. The use of C printf() formatting sequence (beginning by the character %) is also allowed. The following control sequences are available:

Format sequence | type of the argument | Description
~Na | atom | print the atom without quoting. N is minimal number of characters to print using spaces on the right if needed (default: the length of the atom)
~Nc | character code | print the character associated with the code. N is the number of times to print the character (default: 1)
~Nf ~Ne ~NE ~Ng ~NG | float expression | pass the argument Arg and N to the C printf() function as: if N is not specified printf("%f",Arg) else printf("%.Nf",Arg). Similarly for ~Ne, ~NE, ~Ng and ~NG
~Nd | integer expression | print the argument. N is the number of digits after the decimal point. If N is 0 no decimal point is printed (default: 0)
~ND | integer expression | identical to ~Nd except that ’,’ separates groups of three digits to the left of the decimal point
~Nr | integer expression | print the argument according to the radix N. 2 ≤ N ≤ 36 (default: 8). The letters a-z denote digits > 9
~NR | integer expression | identical to ~Nr except that the letters A-Z denote digits > 9
~Ns | character code list | print exactly N characters (default: the length of the list)
~NS | character list | print exactly N characters (default: the length of the list)
~i | term | ignore the current argument
~k | term | pass the argument to write_canonical/1 (section 8.14.6)
~p | term | pass the argument to print/1 (section 8.14.6)
~q | term | pass the argument to writeq/1 (section 8.14.6)
~w | term | pass the argument to write/1 (section 8.14.6)
~~ | none | print the character ’~’
~Nn | none | print N new-line characters (default: 1)
~N | none | print a new-line character if not at the beginning of a line
~? | atom | use the argument as a nested format string
%F | atom, integer or float expression | interface to the C function printf(3) for outputting atoms (C string), integers and floating point numbers. * are also allowed.

format/2 applies to the current output stream.

Errors

SorA is a variable |  | instantiation_error
Format is a partial list or a list with an element E which is a variable |  | instantiation_error
Arguments is a partial list |  | instantiation_error
Format is neither a partial list nor a list or an atom |  | type_error(list, Format)
Arguments is neither a partial list nor a list |  | type_error(list, Arguments)
an element E of the Format list is neither a variable nor a character code |  | representation_error(character_code, E)
SorA is neither a variable nor a stream-term or alias |  | domain_error(stream_or_alias, SorA)
an element E of Format is not a valid format control sequence |  | domain_error(format_control_sequence, E)
the Arguments list does not contain sufficient elements |  | domain_error(non_empty_list, [])
an element E of the Arguments list is a variable while a non-variable term was expected |  | instantiation_error
an element E of the Arguments list is neither variable nor an atom while an atom was expected |  | type_error(atom, E)
an element E of the Arguments cannot be evaluated as an arithmetic expression while an integer or a floating point number was expected |  | an arithmetic error (section 8.6.1)
an element E of the Arguments list is neither variable nor character code while a character code was expected |  | representation_error(character_code, E)
SorA is not associated with an open stream |  | existence_error(stream, SorA)
SorA is an input stream |  | permission_error(output, stream, SorA)
SorA is associated with a binary stream |  | permission_error(output, binary_stream, SorA)

Portability

GNU Prolog predicates.

#### 8.14.8 portray_clause/2, portray_clause/1

Templates

  portray_clause(+stream_or_alias, +clause)
  portray_clause(+clause)

Description

portray_clause(SorA, Clause) pretty prints Clause to the stream associated with the stream-term or alias SorA. portray_clause/2 uses the variable binding predicates name_singleton_vars/1 (section 8.5.1) and numbervars/1 (section 8.5.3). This predicate is used by listing/1 (section 8.23.3).

portray_clause/1 applies to the current output stream.

Errors

Clause is a variable |  | instantiation_error
Clause is neither a variable nor a callable term |  | type_error(callable, Clause)
SorA is a variable |  | instantiation_error
SorA is neither a variable nor a stream-term or alias |  | domain_error(stream_or_alias, SorA)
SorA is not associated with an open stream |  | existence_error(stream, SorA)
SorA is an input stream |  | permission_error(output, stream, SorA)
SorA is associated with a binary stream |  | permission_error(output, binary_stream, SorA)

Portability

GNU Prolog predicates.

#### 8.14.9 get_print_stream/1

Templates

  get_print_stream(?stream)

Description

get_print_stream(Stream) unifies Stream with the stream-term associated with the output stream used by print/2 (section 8.14.6). The purpose of this predicate is to allow a user-defined portray/1 predicate to identify the output stream in use.

Errors

Stream is neither a variable nor a stream-term |  | domain_error(stream, Stream)

Portability

GNU Prolog predicate.

#### 8.14.10 op/3

Templates

  op(+integer, +operator_specifier, +atom_or_atom_list)

Description

op(Priority, OpSpecifier, Operator) alters the operator table. Operator is declared as an operator with properties defined by specifier OpSpecifier and Priority. Priority must be an integer ≥ 0 and ≤ 1200. If Priority is 0 then the operator properties of Operator (if any) are canceled. Operator may also be a list of atoms in which case all of them are declared to be operators. In general, operators can be removed from the operator table and their priority or specifier can be changed. However, it is an error to attempt to change the ’,’ operator from its initial status. An atom can have multiple operator definitions (e.g. prefix and infix like +) however an atom cannot have both an infix and a postfix operator definitions.

Operator specifiers: the following specifiers are available:

Specifier | Type | Associativity
fx | prefix | no
fy | prefix | yes
xf | postfix | no
yf | postfix | yes
xfx | infix | no
yfx | infix | left
xfy | infix | right

Prolog predefined operators:

Priority | Specifier | Operators
1200 | xfx | :- -->
1200 | fx | :-
1105 | xfy | |
1100 | xfy | ;
1050 | xfy | -> *->
1000 | xfy | ,
900 | fy | \+
700 | xfx | = \= =.. == \== @< @=< @> @>= is =:= =\= < =< > >=
600 | xfy | :
500 | yfx | + - /\ \/
400 | yfx | * / // rem mod div << >>
200 | xfx | ** ^
200 | fy | + - \

FD predefined operators:

Priority | Specifier | Operators
750 | xfy | #<=> #\<=>
740 | xfy | #==> #\==>
730 | xfy | ## #\/ #\\/
720 | yfx | #/\ #\/\
710 | fy | #\
700 | xfx | #= #\= #< #=< #> #>= #=# #\=# #<# #=<# #># #>=#
500 | yfx | + -
400 | yfx | * / // rem
200 | xfy | **
200 | fy | + -

Errors

Priority is a variable |  | instantiation_error
OpSpecifier is a variable |  | instantiation_error
Operator is a partial list or a list with an element E which is a variable |  | instantiation_error
Priority is neither a variable nor an integer |  | type_error(integer, Priority)
OpSpecifier is neither a variable nor an atom |  | type_error(atom, OpSpecifier)
Operator is neither a partial list nor a list nor an atom |  | type_error(list, Operator)
an element E of the Operator list is neither a variable nor an atom |  | type_error(atom, E)
Priority is an integer not ≥ 0 and ≤ 1200 |  | domain_error(operator_priority, Priority)
OpSpecifier is not a valid operator specifier |  | domain_error(operator_specifier, OpSpecifier)
Operator (or an element of the Operator list) is ’,’ |  | permission_error(modify, operator, ’,’)
OpSpecifier is a specifier such that Operator would have a postfix and an infix definition. |  | permission_error(create, operator, Operator)
Operator (or an element of the Operator list) is | and it would have a prefix or a postfix definition or its Priority would be ≤ 1100. |  | permission_error(create, operator, ’|’)
Operator (or an element of the Operator list) is [] or {}. |  | permission_error(create, operator, Operator)

Portability

ISO predicate.

The ISO reference implies that if a program calls current_op/3, then modifies an operator definition by calling op/3 and backtracks into the call to current_op/3, then the changes are guaranteed not to affect that current_op/3 goal. This is not guaranteed by GNU Prolog.

#### 8.14.11 current_op/3

Templates

  current_op(?integer, ?operator_specifier, ?atom)

Description

current_op(Priority, OpSpecifier, Operator) succeeds if Operator is an operator with properties defined by specifier OpSpecifier and Priority. This predicate is re-executable on backtracking.

Errors

Priority is neither a variable nor an operator priority |  | domain_error(operator_priority, Priority)
OpSpecifier is neither a variable nor an operator specifier |  | domain_error(operator_specifier, OpSpecifier)
Operator is neither a variable nor an atom |  | type_error(atom, Operator)

Portability

ISO predicate.

#### 8.14.12 char_conversion/2

Templates

  char_conversion(+character, +character)

Description

char_conversion(InChar, OutChar) alters the character-conversion mapping. This mapping is used by the following read predicates: read_term/3 (section 8.14.1), read_atom/2, read_integer/2, read_number/2 (section 8.14.2) and read_token/2 (section 8.14.3) to replace any occurrence of a character InChar by OutChar. However the conversion mechanism should have been previously activated by switching on the char_conversion Prolog flag (section 8.22.1). When InChar and OutChar are the same, the effect is to remove any conversion of a character InChar.

Note that the single character read predicates (e.g. get_char/2) never do character conversion. If such behavior is required, it must be explicitly done using current_char_conversion/2 (section 8.14.13).

Errors

InChar is a variable |  | instantiation_error
OutChar is a variable |  | instantiation_error
InChar is neither a variable nor a character |  | type_error(character, InChar)
OutChar is neither a variable nor a character |  | type_error(character, OutChar)

Portability

ISO predicate. The type_error(character,…) is a GNU Prolog behavior, the ISO reference instead defines a representation_error(character) in this case. This seems to be an error of the ISO reference since, for many other built-in predicates accepting a character (e.g. char_code/2, put_char/2), a type_error is raised.

The ISO reference implies that if a program calls current_char_conversion/2, then modifies the character mapping by calling char_conversion/2, and backtracks into the call to current_char_conversion/2 then the changes are guaranteed not to affect that current_char_conversion/2 goal. This is not guaranteed by GNU Prolog.

#### 8.14.13 current_char_conversion/2

Templates

  current_char_conversion(?character, ?character)

Description

current_char_conversion(InChar, OutChar) succeeds if the conversion of InChar is OutChar according to the character-conversion mapping. In that case, InChar and OutChar are different. This predicate is re-executable on backtracking.

Errors

InChar is neither a variable nor a character |  | type_error(character, InChar)
OutChar is neither a variable nor a character |  | type_error(character, OutChar)

Portability

ISO predicate. Same remark as for char_conversion/2 (section 8.14.12).

Copyright (C) 1999-2021 Daniel Diaz Verbatim copying and distribution of this entire article is permitted in any medium, provided this notice is preserved. More about the copyright