Página 1 de 1

Manipulação de erros no Clipper

Enviado: 23 Dez 2010 12:49
por ziul
Criei a função listada abaixo, para manipulação de erros no Clipper, que grava detalhes do erro e encerra o programa.
O que eu não consigo é manipular o erro e não encerrar o programa.
Fica em loop chamando a função ErrInfo() direto.
Com faço para desabilitar a situação de erro, para continuar o programa?

Código: Selecionar todos

.
ErrorBlock( { |X| ErrInfo(X) } )  
.
Function ErrInfo(X)
  use ERROSYS
  appe blank
  repla ERS_LINHA with '********** Data: ' + dtoc(date())
  appe blank
  repla ERS_LINHA with 'Descricao.: ' + X:Description
  appe blank
  repla ERS_LINHA with 'Arquivo...: ' + X:Filename
  appe blank
  repla ERS_LINHA with 'Campo.....: ' + X:Operation
  quit
  return NIL

Manipulação de erros no Clipper

Enviado: 23 Dez 2010 22:29
por Pablo César
Ziul,

Eu não usaria um dbf para tratar o erro do seu sistema. Ao invés disso, eu geraria em arquivo texto através FWRITE. Na internet tem vários exemplos. E o que você deseja fazer, na minha opinião não deveria continuar o sistema, pois se houve erro, deve ser tratado, seja por motivo de erro de programação, crash no ambiente ou qualquer outro. Mas que o sistema deve parar, na maioria das vezes (na minha opinião): deve parar. Mas senão me engano o tratamento feito no errorsys.prg é para não utilizar o "break", "RETURN(.F.)" e "QUIT" (veja o código abaixo do proprio source do Clipper).

Código: Selecionar todos

/***
*
*	Errorsys.prg
*
*  Standard Clipper error handler
*
*  Copyright (c) 1990-1993, Computer Associates International, Inc.
*  All rights reserved.
*
*  Compile:  /m /n /w
*
*/

#include "error.ch"


// put messages to STDERR
#command ? <list,...>   =>  ?? Chr(13) + Chr(10) ; ?? <list>
#command ?? <list,...>  =>  OutErr(<list>)


// used below
#define NTRIM(n)		( LTrim(Str(n)) )



/***
*	ErrorSys()
*
*	Note:  automatically executes at startup
*/

proc ErrorSys()
	ErrorBlock( {|e| DefError(e)} )
return




/***
*	DefError()
*/
static func DefError(e)
local i, cMessage, aOptions, nChoice



	// by default, division by zero yields zero
	if ( e:genCode == EG_ZERODIV )
		return (0)
	end


	// for network open error, set NETERR() and subsystem default
	if ( e:genCode == EG_OPEN .and. e:osCode == 32 .and. e:canDefault )

		NetErr(.t.)
		return (.f.)									// NOTE

	end


	// for lock error during APPEND BLANK, set NETERR() and subsystem default
	if ( e:genCode == EG_APPENDLOCK .and. e:canDefault )

		NetErr(.t.)
		return (.f.)									// NOTE

	end



	// build error message
	cMessage := ErrorMessage(e)


	// build options array
	// aOptions := {"Break", "Quit"}
	aOptions := {"Quit"}

	if (e:canRetry)
		AAdd(aOptions, "Retry")
	end

	if (e:canDefault)
		AAdd(aOptions, "Default")
	end


	// put up alert box
	nChoice := 0
	while ( nChoice == 0 )

		if ( Empty(e:osCode) )
			nChoice := Alert( cMessage, aOptions )

		else
			nChoice := Alert( cMessage + ;
							";(DOS Error " + NTRIM(e:osCode) + ")", ;
							aOptions )
		end


		if ( nChoice == NIL )
			exit
		end

	end


	if ( !Empty(nChoice) )

		// do as instructed
		if ( aOptions[nChoice] == "Break" )
			Break(e)

		elseif ( aOptions[nChoice] == "Retry" )
			return (.t.)

		elseif ( aOptions[nChoice] == "Default" )
			return (.f.)

		end

	end


	// display message and traceback
	if ( !Empty(e:osCode) )
		cMessage += " (DOS Error " + NTRIM(e:osCode) + ") "
	end

	? cMessage
	i := 2
	while ( !Empty(ProcName(i)) )
		? "Called from", Trim(ProcName(i)) + ;
			"(" + NTRIM(ProcLine(i)) + ")  "

		i++
	end


	// give up
	ErrorLevel(1)
	QUIT

return (.f.)




/***
*	ErrorMessage()
*/
static func ErrorMessage(e)
local cMessage


	// start error message
	cMessage := if( e:severity > ES_WARNING, "Error ", "Warning " )


	// add subsystem name if available
	if ( ValType(e:subsystem) == "C" )
		cMessage += e:subsystem()
	else
		cMessage += "???"
	end


	// add subsystem's error code if available
	if ( ValType(e:subCode) == "N" )
		cMessage += ("/" + NTRIM(e:subCode))
	else
		cMessage += "/???"
	end


	// add error description if available
	if ( ValType(e:description) == "C" )
		cMessage += ("  " + e:description)
	end


	// add either filename or operation
	if ( !Empty(e:filename) )
		cMessage += (": " + e:filename)

	elseif ( !Empty(e:operation) )
		cMessage += (": " + e:operation)

	end


return (cMessage)
Até também existem exemplos aqui que dá para enviar por email o erro, ja pensou nisso ?

https://pctoledo.org/forum/viewto ... 707#p43707

Re: Manipulação de erros no Clipper

Enviado: 24 Dez 2010 07:30
por Toledo
Bom, você pode usar alguma estrutura com o comando BEGIN SEQUENCE... END SEQUENCE, por exemplo dentro do menu principal do seu programa, ai no errorsys use o comando BREAK que vai retornar a execução depois de END SEQUENCE.

Veja também:
https://pctoledo.org/forum/fileba ... t=s&page=1

Abraços,

Re: Manipulação de erros no Clipper

Enviado: 27 Dez 2010 12:21
por rochinha
Amiguinhos,

Eis um trecho de código que eu estava procurando e acabei encontrando em uma de minhas biblias de Clipper.

Trata-se de um código desenvolvido por Stephen J. Straley para manipulação de erro e permissão de altaração do fluxo em runtime.

Código: Selecionar todos

FUNCTION undef_error( a1, a2, a3, a4, a5 )
   ret_row = row()
   ret_col = col()
   sounderr()
   errorscr = savescreen(17,10,24,70)
   @ 17,10 clear to 24,70
   @ 17,10 to 24,70 double
   @ 17,12 say "< OCORRENCIA DE ERRO ON-LINE >"
   @ 19,12 say "ocorreu um &a3. no programa/funcao"
   @ 20,12 say "modulo &a1., no arquivo "+procfile()+" na linha "+alltrim(str(a2))
   DO CASE
      CASE "UNDEFINED IDENTIFIER" $ upper(a3)
           DO WHILE .t.
              @ 23,12 say "Insira tipo de dado de &a5. (DNCL)"
              dataset = upper(chr(inkey(0)))
              IF     dataset = "D"
                     error = ctod("  /  /  ")
                     errpic= "99/99/99"
              ELSEIF dataset = "L"
                     error = .f.
                     errpic= ""
              ELSEIF dataset = "N"
                     error = 1000000000.000000 - 1000000000.000000
                     errpic= "999999999999.999999999999"
              ELSEIF dataset = "C"
                     @ 23,12 say space(len("Insira o tipo de dado de &a5. (DNCL)"))
                     error = ctod("  /  /  ")
                     error1= 0
                     @ 23,12 say "Insira tamanho da string => " get error1 valid error1 >= 1 .and. error1 < 3000
                     READ
                     @ 23,12 say "                            "
                     error = space(error1)
                     errpic= if(error1 > 20, "@S20", "@X")
              ELSE
                     LOOP
              ENDIF
              EXIT
           ENDDO
           @ 23,12 say space(len("Insira o tipo de dado de &a5. (DNCL)"))
           @ 23,12 say "Insira o novo valor para &a5. =>" get error pict errpic
           READ
           PUBLIC &a5.
           STORE erro TO &a5.
           IF     dataset = "L"
                  errmess = "STORE "+if(error,".t.",".f.")+" TO &a5."
           ELSEIF dataset = "D"
                  errmess = "STORE ctod("+alltrim(strvalue(error))+") TO &a5."
           ELSEIF dataset = "C"
                  errmess = "STORE ["+alltrim(strvalue(error))+"] TO &a5."
           ELSE
                  errmess = "STORE "+alltrim(strvalue(error))+" TO &a5."
           ENDIF
   ENDCASE
   
FUNCTION sounderr
   tone(700,8)
   inkey(.3)
   tone(700,8)
   inkey(.3)
   tone(700,8)
   return

FUNCTION strvalue( showstring )
   DO CASE
      CASE TYPE("showstring") = "C"
           RETURN ("showstring")
      CASE TYPE("showstring") = "N"
           RETURN STR("showstring")
      CASE TYPE("showstring") = "M"
           RETURN " "
      CASE TYPE("showstring") = "D"
           RETURN DTOC("showstring")
      CASE TYPE("showstring") =
           RETURN ("showstring")
      OTHERWISE
           RETURN IIF(showstring,"Verdadeiro","Falso")
   ENDCASE
Este código segue a sintaxe Summer 87.