Page 1 of 1

Register recovery error(is this a bug or faults of my code?)

Posted: Fri Jul 22, 2005 11:27 pm
by sonic3d
I recently wrote these code,and suffered written to readonly memory error.
I debuged the code in IDA,and found after all the code of this function executed,the return address in stack is pointed error by ESP(four bytes lower than the exact address which stored the correct return address)

Some one help me?

*Note1:The messagebox call--MessageRequester("Hello","HelloText") is added for easy deassembly,you can rip it out.
*Note2:The purpose of these code is to process a line in the specific CSV format file.

Code: Select all

Procedure.s GetCsvItemString(*FullString.s)
  MessageRequester("Hello","HelloText")
  StartPos.l=0
  EndPos.l=0
  RtString.s = ""
  If (Chr(34)=Left(*FullString.s,1))
    StartPos.l=2
    EndPos.l = FindString(*FullString.s,Chr(34)+",",2)
    RtString.s = Mid(*FullString.s,StartPos.l,EndPos-StartPos)
    *FullString.s = Mid(*FullString.s,EndPos+2,Len(*FullString.s)-EndPos+1-2)
  Else
    StartPos.l=1
    EndPos.l = FindString(*FullString.s,",",1)
    RtString.s = Mid(*FullString.s,StartPos.l,EndPos-StartPos)
    *FullString.s = Mid(*FullString.s,EndPos+1,Len(*FullString.s)-EndPos+1-1)
  EndIf
  MessageRequester("Hello","HelloText")
  ProcedureReturn RtString
EndProcedure

Title.s = GetCsvItemString(CurrLineText$)

Posted: Sat Jul 23, 2005 2:47 am
by fweil
sonic3d,

Maybe yur idea was like that ?

Code: Select all

Procedure.s GetCsvItemString(FullString.s)
  StartPos.l = 0
  EndPos.l = 0
  RtString.s = ""
  If Left(FullString.s, 1) = Chr(34)
    StartPos.l = 2
    EndPos.l = FindString(FullString.s, Chr(34) + ",", 2)
    RtString.s = Mid(FullString.s, StartPos.l, EndPos - StartPos)
    FullString.s = Mid(FullString.s, EndPos + 2, Len(FullString.s) - EndPos + 1 - 2)
  Else
    StartPos.l = 1
    EndPos.l = FindString(FullString.s, ",", 1)
    RtString.s = Mid(FullString.s, StartPos.l, EndPos - StartPos)
    FullString.s = Mid(FullString.s, EndPos + 1,Len(FullString.s) - EndPos + 1 - 1)
  EndIf
  ProcedureReturn RtString
EndProcedure

CurrLineText$ = "Title, sub title"
MessageRequester("Hello", GetCsvItemString(CurrLineText$), #PB_MessageRequester_Ok)
CurrLineText$ = Chr(34) + "Title" + Chr(34) + ", " + Chr(34) + "sub title" + Chr(34)
MessageRequester("Hello", GetCsvItemString(CurrLineText$), #PB_MessageRequester_Ok)
Let me know if I was wrong ...

Posted: Sat Jul 23, 2005 11:08 am
by sonic3d
Thanks,fweil! :lol:

But my purpose is to process a line in CSV file like this(Shoud be in one line):

Code: Select all

1,"SAS/ETS 9.1 User's Guide. Volume 1",,"SAS Publishing",2004,108350,0,SAS/ETS.,005.36,"HA30.3.S274 2004eb",Available,$231.95,,1590472446',1590474120',
some items in this string contain quote which should be stripped,and other values contain no quote can be directly stored.Finally, return the stored string.
***Why I use string point value as parameter of this function is for an easy changing to the *FullString.s I passed in.After the function finished get the first item from *FullString.s, the first item and the followed comma will be removed so that the *FullString.s could be pass to the function again to get next item easily without additional change outside this function.

Thus,point value is must to be used I thought.

But how can I deal this retvalue/stack prob?
I can change the machine code after compiled,but it's not a good way I thought.

Somebody help me! :shock:

Posted: Sat Jul 23, 2005 2:13 pm
by fweil
sonic3d,

Well, I guess I understand well what you need.

The problem is to parse fields, usually coma separated, by getting them one after the other from a procedure that will process the good stuf to separate them.

The best way I suppose is to use StringField() command. Then from each field you can change anything you want in fields or transpose characters to values etc.

My way to code such behaviour would be something like the following sample code. I made a more generic string parser with separator and delimiter args for possible extended use.

Here the procedure improves the StringField() function.

Code: Select all

Procedure.s EnumCSVFields(String.s, Status.l, Separator.s, Delimiter.s)
  Static FieldID
    If Status = #FALSE
        FieldID = -1
    EndIf
    FieldID + 1
    Field.s = StringField(String, FieldID, Separator)
    If Left(Field, 1) = Delimiter And Right(Field, 1) = Delimiter
        Field = Mid(Field, 2, Len(Field) - 2)
    EndIf
    ProcedureReturn Field
EndProcedure

;
;
;
  Result.s = ""
  String.s = "1," + Chr(34) + "SAS/ETS 9.1 User's Guide. Volume 1" + Chr(34) + ",," + Chr(34) + "SAS Publishing" + Chr(34) + ",2004,108350,0,SAS/ETS.,005.36," + Chr(34) + "HA30.3.S274 2004eb" + Chr(34) + ",Available,$231.95,,1590472446',1590474120',"
  EnumCSVFields(String, #FALSE, ",", Chr(34))
  For i = 1 To 30
    Result + "Field " + Str(i) + " contains : " + EnumCSVFields(String, #TRUE, ",", Chr(34)) + Chr(10) + Chr(13)
  Next
  MessageRequester("Results", Result, #PB_MessageRequester_OK)

  Result.s = ""
  String = "http://www.google.com/search?hl=en&as_qdr=all&q=%22string%22+filetype%3Apb&btnG=Search&lr="
  EnumCSVFields(String, #FALSE, "&", Chr(34))
  For i = 1 To 30
    Result + "Field " + Str(i) + " contains : " + EnumCSVFields(String, #TRUE, "&", Chr(34)) + Chr(10) + Chr(13)
  Next
  MessageRequester("Results", Result, #PB_MessageRequester_OK)

Posted: Sat Jul 23, 2005 7:07 pm
by sonic3d
Thanks again fweil!!

You really gimme a new idea.And also,great code you post.
I tried your code and it work well in most case.Only a little problem when process string like this one:

Code: Select all

1,"Advanced Topics in Database Research. Volume 4","Siau, Keng","Idea Group Publishing",2005,126093,0,"Database management.",005.74,"QA76.9.D3A38eb vol. 4",Available,$84.95,,1591404711',1591404738',
The third item which contain comma within quote will be parsed as two items.Still nice code you wrote.Thanks again!!! :wink:

Finally I decided to solve the problem in my original function.And now I have found a way to solve it.
Code changed to:

Code: Select all

Procedure.s GetCsvItemString(*FullString)
  StartPos.l = 0
  EndPos.l = 0
  RtString.s = ""
  QuoteChar.s=Chr(34)
  MyFullStr.s=PeekS(*FullString,2048)
  If (QuoteChar=Left(MyFullStr,1))
    StartPos.l=2
    EndPos.l = FindString(MyFullStr,Chr(34)+",",2)
    RtString.s = Mid(MyFullStr,StartPos.l,EndPos-StartPos)
    MyFullStr = Mid(MyFullStr,EndPos+2,Len(MyFullStr)-EndPos+1-2)
  Else
    StartPos.l=1
    EndPos.l = FindString(MyFullStr,",",1)
    RtString.s = Mid(MyFullStr,StartPos.l,EndPos-StartPos)
    MyFullStr = Mid(MyFullStr,EndPos+1,Len(MyFullStr)-EndPos+1-1)
  EndIf
  PokeS(*FullString, MyFullStr, 2048)
  ProcedureReturn RtString
EndProcedure
The key part is changing

Code: Select all

If (Chr(34)=Left(MyFullStr,1))
into
QuoteChar.s=Chr(34)

Code: Select all

If (QuoteChar=Left(MyFullStr,1))
and the similiar thing may happened on compare with other special chars.
For example:

Code: Select all

Procedure.l LoadCsvItem2()
  CurrLineText$="hello"
  While ("" <> CurrLineText$)
  Wend
  ProcedureReturn CsvItemCount
EndProcedure
Call this function will cause return address restore error.It must be changed to

Code: Select all

Procedure.l LoadCsvItem2()
  CurrLineText$="hello"
  EmptyChar.s=""
  While (EmptyChar <> CurrLineText$)
  Wend
  ProcedureReturn CsvItemCount
EndProcedure

I believe this is a bug of PB 3.93