Guia de rastreamento dinâmico Solaris

printf()

A função printf() combina a capacidade de rastrear dados, como se fosse a função trace(), com a capacidade de produzir a saída de dados e de outro texto em um formato específico descrito por você. A função printf() informa ao DTrace para rastrear os dados associados a cada argumento após o primeiro argumento e depois para formatar os resultados usando as regras descritas pelo primeiro argumento de printf (), conhecido como seqüência de formato.

A seqüência de formato é uma seqüência regular que contém inúmeras conversões de formato, cada uma começando com o caractere %, que descreve como formatar o argumento correspondente. A primeira conversão na seqüência de formato corresponde ao segundo argumento printf(), a segunda conversão ao terceiro argumento, e assim por diante. Todo o texto entre conversões é impresso textualmente. O caractere que segue o caractere de conversão % descreve o formato a ser usado para o argumento correspondente.

Ao contrário de printf(3C), DTrace printf() é uma função incorporada que é reconhecida pelo compilador de D. O compilador de D fornece vários serviços úteis do DTrace printf() que não são encontrados na biblioteca de C printf():

Para implementar esses recursos, a seqüência de formato na função printf() do DTrace deve ser especificada como uma constante de seqüência em seu programa em D. As seqüências de formato podem ser variáveis dinâmicas do tipo string.

Especificações de conversão

Cada especificação de conversão na seqüência de formato é introduzida pelo caractere %, após o qual as informações seguintes aparecem em seqüência:

A função printf(3C) também aceita as especificações de conversão do formato % n$ onden é um inteiro decimal. A printf() do DTrace não aceita este tipo de especificação de conversão.

Especificadores de sinalizador

Os sinalizadores de conversão printf() são ativados pela especificação de um ou mais dos seguintes caracteres, que podem aparecer em qualquer ordem:

'

A porção inteira do resultado de uma conversão decimal (%i, %d, %u, %f, %g ou %G) é formatada com milhares de caracteres de agrupamento por meio do caractere de agrupamento não-monetário. Algumas localidades, incluindo a localidade POSIX C, não fornece caracteres de agrupamento não-monetários a serem usados com este sinalizador.

-

O resultado da conversão é justificado à esquerda no campo. A conversão será justificada à direita, se este sinalizador não for especificado.

+

O resultado da conversão assinada sempre começa com um sinal (+ ou -). Se este sinalizador não for especificado, a conversão começa com um sinal somente quando um valor negativo for convertido.

espaço

Se o primeiro caractere de uma conversão assinada não for um sinal ou se uma conversão assinada resultar em nenhum caractere, um espaço será colocado antes do resultado. Se os sinalizadores espaço e + aparecerem, o sinalizador de espaço será ignorado.

#

O valor será convertido em um formato alternativo, se for definido um formato alternativo para a conversão selecionada. Os formatos alternativos para conversões são descritos junto com a conversão correspondente.

0

Para as conversões d, i, o, u, x, X, e, E, f, g, e G, zeros à esquerda (seguindo qualquer indicação de sinal ou base) são usados para preencher a largura do campo. Nenhum preenchimento de espaço é realizado. Se os sinalizadores 0 e - aparecerem, o sinalizador 0 será ignorado. Para as conversões d, i, o, u, x e X, se uma precisão for especificada, o sinalizador 0 será ignorado. Se os sinalizadores 0 e ' aparecerem, os caracteres de agrupamento serão inseridos antes do preenchimento de zero.

Especificadores de largura e de precisão

A largura de campo mínima pode ser especificada como uma seqüência de dígitos decimais seguindo qualquer especificador de sinalizador, nesse caso, a largura do campo é definida como o número de colunas especificadas. A largura do campo também pode ser especificada como um asterisco (*), nesse caso, um argumento adicional do tipo int é acessado para determinar a largura do campo. Por exemplo, para imprimir um inteiro x em uma largura de campo determinada pelo valor da variável int w, você escreveria a declaração de D:

printf("%*d", w, x);

A largura do campo também pode ser especificada com um caractere ? para indicar que a largura do campo deve ser definida com base no número de caracteres necessários para formatar um endereço em hexadecimal no modelo de dados do kernel do sistema operacional. A largura será definida como 8, se o kernel estiver usando o modelo de dados de 32 bits, ou como 16 se o kernel estiver usando o modelo de dados de 64 bits.

A precisão da conversão pode ser especificada como uma seqüência de dígitos decimais seguindo um ponto (.) ou por um asterisco ( *) seguindo um ponto. Se um asterisco for usado para especificar a precisão, um argumento adicional do tipo int anterior ao argumento de conversão será acessado para determinar a precisão. Se a largura e a precisão forem especificadas como asteriscos, a ordem de argumentos para printf() da conversão deve aparecer na seguinte ordem: largura, precisão, valor.

Prefixos de tamanho

Os prefixos de tamanho são necessários nos programas em ANSI-C que usam printf(3C) a fim de indicar o tamanho e o tipo do argumento de conversão. O compilador de D realiza esse processamento para as suas chamadas printf () automaticamente, sendo assim, os prefixos de tamanho não são necessários. Embora os prefixos de tamanho sejam fornecidos para compatibilidade com C, seu uso é explicitamente desencorajado nos programas em D porque eles vinculam o código a um modelo de dados específico quando usam tipos derivados. Por exemplo, se um typedef for redefinido como tipos base de inteiro diferentes, dependendo do modelo de dados, não será possível usar uma única conversão de C que funcione em ambos os modelos de dados sem conhecer explicitamente os dois tipos subjacentes, incluindo uma expressão de conversão ou definindo várias seqüências de formato. O compilador de D resolve esse problema automaticamente, permitindo que você omita os prefixos de tamanho e determine automaticamente o tamanho do argumento.

Os prefixos de tamanho podem ser colocados logo antes do nome de conversão e após quaisquer sinalizadores, larguras e especificadores de precisão. Os prefixos de tamanho são da seguinte forma:

Formatos de conversão

Cada seqüência de caractere de conversão resulta na busca de zero ou mais argumentos. Se forem fornecidos argumentos insuficientes para a seqüência de formato, ou se a seqüência de formato estiver exaurida e os argumentos permanecerem, o compilador de D emitirá uma mensagem de erro apropriada. Se um formato de conversão indefinido for especificado, o compilador de D emite uma mensagem de erro apropriada. As seqüências de caracteres de conversão são:

a

O ponteiro ou argumento uintptr_t é impresso como um nome de símbolo de kernel no formato módulo`nome do símbolo mais um deslocamento de byte hexadecimal opcional. Se o valor não estiver no intervalo definido por um símbolo de kernel definido, o valor será impresso como um inteiro hexadecimal.

c

O argumento char, short ou int é impresso como um caractere ASCII.

C

O argumento char, short ou int será impresso como um caractere ASCII, se o caractere for um caractere ASCII imprimível. Se o caractere não for um caractere imprimível, ele será impresso com a seqüência de escape correspondente, conforme mostrado na Tabela 2–5.

d

O argumento char, short, int, long ou long long é impresso como um inteiro decimal (base 10). Se o argumento for signed, ele será impresso como um valor assinado. Se o argumento for unsigned, ele será impresso como um valor não assinado. Esta conversão possui o mesmo significado que i.

e, E

O argumento float, double ou long double é convertido para o estilo [-] d.ddddd, onde existe um dígito antes do caractere fracionário e o número de dígitos depois dele é igual à precisão. O caractere fracionário será diferente de zero, se o argumento for diferente de zero. Se a precisão não for especificada, o valor de precisão padrão será 6. Se a precisão for 0 e o sinalizador # não estiver especificado, nenhum caractere fracionário aparecerá. O formato de conversão E produz um número com E em vez de e introduzindo o expoente. O expoente sempre contém pelo menos dois dígitos. O valor é arredondado pra o número apropriado de dígitos.

f

O argumento float, double ou long double é convertido para o estilo [-] ddd.ddd, onde número de dígitos após o caractere de precisão é igual à especificação de precisão. Se a precisão não for especificada, o valor de precisão padrão será 6. Se a precisão for 0 e o sinalizador # não estiver especificado, nenhum caractere fracionário aparecerá. Se um caractere fracionário aparecer, pelo menos um dígito aparecerá antes dele. O valor é arredondado pra o número apropriado de dígitos.

g, G

O argumento float, double ou long double é impresso no estilo f ou e (ou no estilo E no caso de um caractere de conversão G), com a precisão especificando o número de dígitos significativos. Se uma precisão explícita for 0, ela é considerada como 1. O estilo usado depende do valor convertido: o estilo e (ou E) será usado somente se o expoente resultante da conversão for menor que -4 ou maior ou igual à precisão. Zeros à direita são removidos da parte fracionária do resultado. Um caractere fracionário aparecerá somente se for seguido por um dígito. Se o sinalizador # for especificado, os zeros à direita não serão removidos do resultado.

i

O argumento char, short, int, long ou long long é impresso como um inteiro decimal (base 10). Se o argumento for signed, ele será impresso como um valor assinado. Se o argumento for unsigned, ele será impresso como um valor não assinado. Esta conversão tem o mesmo sentido de d.

o

O argumento char, short, int, long ou long long é impresso como um inteiro octal não assinado (base 8). Os argumentos que são signed ou unsigned podem ser usados com esta conversão. Se o sinalizador # for especificado, a precisão do resultado será aumentada, se necessário, para forçar o primeiro dígito do resultado a ser zero.

p

O ponteiro ou argumento uintptr_t é impresso como um inteiro hexadecimal (base 16). D aceita argumentos de ponteiro de qualquer tipo. Se o sinalizador # for especificado, um resultado diferente de zero terá 0x anteposto a ele.

s

O argumento deve ser uma matriz de char ou string. Os bytes da matriz ou string são lidos até um caractere nulo de terminação ou o fim dos dados, e interpretados e impressos como caracteres ASCII. Se a precisão não for especificada, ela é considerada como infinita, sendo assim, todos os caracteres até o primeiro caractere nulo serão impressos. Se a precisão for especificada, somente essa parte da matriz de caracteres, que será exibida no número correspondente de colunas da tela, será impressa. Se um argumento do tipo char * for formatado, ele deverá ser convertido para string ou prefixado com o operador stringof de D para indicar que o DTrace deve rastrear os bytes da seqüência e formatá-los.

S

O argumento deve ser uma matriz de char ou string. O argumento é processado como se fosse pela conversão %s, mas quaisquer caracteres ASCII que não sejam imprimíveis serão substituídos pela seqüência de escape correspondente descrita na Tabela 2–5.

u

O argumento char, short, int, long ou long long é impresso como um inteiro decimal não assinado (base 10). Os argumentos que são signed ou unsigned podem ser usados com esta conversão, e o resultado é sempre formatado como unsigned.

wc

O argumento int é convertido em um caractere extenso (wchar_t ) e o caractere extenso resultante é impresso.

ws

O argumento deve ser uma matriz de wchar_t. Os bytes da matriz ou são lidos até um caractere nulo de terminação ou o fim dos dados, e interpretados e impressos como caracteres extensos. Se a precisão não for especificada, ela é considerada como infinita, sendo assim, todos os caracteres extensos até o primeiro caractere nulo serão impressos. Se a precisão for especificada, somente essa parte da matriz de caracteres extensos, que será exibida no número correspondente de colunas da tela, será impressa.

x, X

O argumento char, short, int, long ou long long é impresso como um inteiro hexadecimal não assinado (base 16). Os argumentos que são signed ou unsigned podem ser usados com esta conversão. Se o formato x da conversão for usado, os dígitos de letra abcdef serão usados. Se o formato X da conversão for usado, os dígitos de letra ABCDEF serão usados. Se o sinalizador # for especificado, um resultado diferente de zero terá 0x (para %x) ou 0X (para %X) anteposto a ele.

Y

O argumento uint64_t será interpretado como o número de nanossegundos desde 00:00 Horário Coordenado Universal, 1 de janeiro de 1970, e será impresso no seguinte formato cftime(3C) form: “%Y %a %b %e %T %Z”. O número de nanossegundos desde 00:00 UTC, 1 de janeiro, 1970, está disponível na variável walltimestamp.

%

Imprime um caractere literal %. Nenhum argumento é convertido. A especificação de conversão inteira deve ser %%.