Announcement: Be excellent to each other.


Caravel Forum : Other Boards : Anything : The incredible edible programming thread
Page 1 of 2
2
New Topic New Poll Post Reply
Poster Message
DiMono
Level: Smitemaster
Avatar
Rank Points: 1181
Registered: 09-13-2003
IP: Logged
icon The incredible edible programming thread (0)  
The Development forum is for DROD projects specifically, so this seemed the best place to put this. We have lots of programmers on this site, and everyone runs in to problems once in a while. This is a place for us to put our heads together and get through our problems. Here's mine to start us off:

I'm developing a bbcode parser that includes a [code] tag for preformatted text, and equates to <pre> and </pre>. I want bbcode inside the pre tags to be displayed, not parsed, so [code][b]this should not be bold[/b][/code] will display [b]this should not be bold[/b] in a fixed width.

The problem is that the parser I'm writing translates all instances of valid bbcode tags to their html equivalents, so I end up with <pre> text <b>text</b> text </pre> <b>un-pre'd text</b> <pre> text <i>text</i> text </pre>. I thus need a way to replace instances of < with < and > with > between the <pre> and </pre> tags. This seems simple enough, except any regular expression I can get to work always ends up in greedy mode eventually, unformatting the </pre> and <pre> in the middle.

Does anyone know a way to pick this apart in php, preferably using regular expressions? Closest I can figure the expression I need is something like:

<pre>(?!</pre>)*<(?!/pre>)

which should in theory find a <pre>, then any < where there is no </pre> between them that isn't itself a </pre>, but it always matches nothing. Is there a way to do this, or am I resigned to parsing the string manually?

____________________________
Deploy the... I think it's a yellow button... it's usually flashing... it makes the engines go... WHOOSH!
10-19-2005 at 04:10 PM
View Profile Send Private Message to User Send Email to User Visit Homepage Show all user's posts This architect's holds Quote Reply
stigant
Level: Smitemaster
Avatar
Rank Points: 1182
Registered: 08-19-2004
IP: Logged
icon Re: The incredible edible programming thread (0)  
Could you use an expression like
<pre>*</pre>
to find all code between pre tags and then use
<*>
on that to find all tags in the code?

I'm not familiar with bbcode and its been a while since I used regular expressions, so feel free to tell me I know nothing and I'll go away quietly.

____________________________
Progress Quest Progress
10-19-2005 at 04:43 PM
View Profile Send Private Message to User Show all user's posts Quote Reply
DiMono
Level: Smitemaster
Avatar
Rank Points: 1181
Registered: 09-13-2003
IP: Logged
icon Re: The incredible edible programming thread (0)  
I found a way to brute force it using string functions:
function fixpretext($broken) {
   $broken = str_replace('<', '<', $broken);
   $broken = str_replace('>', '>', $broken);
   $broken = str_replace('<br />', '<br />', $broken);
   return $broken;
}

$original = "string to be parsed";
while ($original) {
   if (strstr($original, '<pre>')) {
      $new .= substr($original, 0, strpos($original, '<pre>') + 5); // capture up to and including <pre>
      $original = substr($original, strpos($original, '<pre>') + 5); // strip it from original text
      $parseme = substr($original, 0, strpos($original, '</pre>'); // capture inside <pre></pre>
      $original = substr($original, strpos($original, '</pre>'); // strip it from original text
      $parseme = fixpretext($parseme); // parse it
      $new .= $parseme; // add parsed to output
   } else {
      $new .= $original; // add the remaining text to the parsed string
      $original = false; // exit the loop
   }
}

I'm convinced there's a way to do it using pure regexp though, all I need is a way to match !</pre> over * characters

____________________________
Deploy the... I think it's a yellow button... it's usually flashing... it makes the engines go... WHOOSH!
10-19-2005 at 04:48 PM
View Profile Send Private Message to User Send Email to User Visit Homepage Show all user's posts This architect's holds Quote Reply
trick
Level: Legendary Smitemaster
Rank Points: 2580
Registered: 04-12-2003
IP: Logged
icon Re: The incredible edible programming thread (+1)  
Er, are you sure that's what you want ? Maybe I misunderstood the problem, but it seems to me what you want to do is fix the bbcode parser to not replace any bbcode tags within the [code] tags in the first place. &, < and > should be replaced by &amp;, &lt; and &gt; anyway, both outside and inside code tags (unless normal html is allowed as well as bbcode, that is). In any case, regular expressions by themselves has no concept of state, so if I'm correct, what you want is a state machine (not anything advanced, a very simple one will do).

- Gerry
10-19-2005 at 05:12 PM
View Profile Send Private Message to User Send Email to User Show all user's posts Quote Reply
DiMono
Level: Smitemaster
Avatar
Rank Points: 1181
Registered: 09-13-2003
IP: Logged
icon Re: The incredible edible programming thread (0)  
Except fixing the parser to not change anything between them still encounters the same problem, only it's looking for text that doesn't satisfy the condition rather than text that does satisfy it. It's the same problem.

The first thing I do is replace the < > and & with entities to strip all html tags. Then I'm replacing the [valid entity] tags with <valid entity>. What I want to do is allow the user to decide whether to have bbcode within a [code] be parsed or not. So I actually want to replace < with [ and > with ], not with the < and > entities, but the dilemma remains the same.

____________________________
Deploy the... I think it's a yellow button... it's usually flashing... it makes the engines go... WHOOSH!

[Last edited by DiMono at 10-19-2005 05:29 PM]
10-19-2005 at 05:28 PM
View Profile Send Private Message to User Send Email to User Visit Homepage Show all user's posts This architect's holds Quote Reply
DiMono
Level: Smitemaster
Avatar
Rank Points: 1181
Registered: 09-13-2003
IP: Logged
icon Re: The incredible edible programming thread (0)  
It's occured to me that [url=] and [img] tags will have to remain unparsed as well, so trick was right that I have to make sure things between [code] aren't parsed at all. I've rewritten my code to satisfy this:
while ($original) {
        if (strpos($original, '[ code]')) {
                $parseme = substr($original, 0, strpos($original, '[ code]'));
                $parseme = preg_replace($patterns, $replaces, $parseme);
                $new .= $parseme . '<pre>';
                $original = substr($original, strpos($original, '[ code]') + 6);
                $new .= substr($original, 0, strpos($original, '[ /code]')) . '</pre>';
                $original = substr($original, strpos($original, '[ /code]') + 7);
        } else {
                $new .= $original;
                $original = '';
        }
}
Considering this, I no longer think there's a feasible way to do it all using pure regexp. Ah well, I tried. Now I need to find a way to deal with nested [code] tags

____________________________
Deploy the... I think it's a yellow button... it's usually flashing... it makes the engines go... WHOOSH!
10-19-2005 at 06:05 PM
View Profile Send Private Message to User Send Email to User Visit Homepage Show all user's posts This architect's holds Quote Reply
trick
Level: Legendary Smitemaster
Rank Points: 2580
Registered: 04-12-2003
IP: Logged
icon Re: The incredible edible programming thread (0)  
DiMono wrote:
It's occured to me that [url=] and [img] tags will have to remain unparsed as well, so trick was right that I have to make sure things between [code] aren't parsed at all.
Not exactly. You still need to change &, < and > into their html entities, otherwise they won't show up properly when shown as html. You don't just switch things on/off based on state, you change it. Some things can behave the same in several states (such as replacing entities in this case).

Now I need to find a way to deal with nested [code] tags
Just keep track of the nesting level in a variable -- increase it when you encounter [code] (and enter "code" state if the nesting level was 0 before), decrease it when you encounter [/code] (and leave "code" state if this leaves the nesting level at 0). Alternately you could use a state stack.

- Gerry

[Last edited by trick at 10-19-2005 06:19 PM]
10-19-2005 at 06:17 PM
View Profile Send Private Message to User Send Email to User Show all user's posts Quote Reply
DiMono
Level: Smitemaster
Avatar
Rank Points: 1181
Registered: 09-13-2003
IP: Logged
icon Re: The incredible edible programming thread (0)  
I always do the initial entity replacement of < > and &.

Except I also need to provide for the possibility of there being an unequal number of [code] and [/code] pairs. Such as this:

[code]showing off the [code] tag[/code]

Right now I'm starting with a preg_match_all for the open and close tags, I just need to figure out the logic for the next part.

____________________________
Deploy the... I think it's a yellow button... it's usually flashing... it makes the engines go... WHOOSH!
10-19-2005 at 06:26 PM
View Profile Send Private Message to User Send Email to User Visit Homepage Show all user's posts This architect's holds Quote Reply
Mattcrampy
Level: Smitemaster
Avatar
Rank Points: 2388
Registered: 05-29-2003
IP: Logged
icon Re: The incredible edible programming thread (0)  
Do you need to deal with nested code tags, though?

____________________________
What do you call an elephant at the North Pole?
Click here to view the secret text

10-19-2005 at 07:07 PM
View Profile Send Private Message to User Send Email to User Show all user's posts Quote Reply
DiMono
Level: Smitemaster
Avatar
Rank Points: 1181
Registered: 09-13-2003
IP: Logged
icon Re: The incredible edible programming thread (0)  
I shouldn't have to deal with them, but that doesn't mean I won't have users who try to use them to break the site. I've decided to not allow them to use different numbers of opening and closing code tags, because of the possibility of posts like this:

[code]Showing off the [code] and [/code] tags. That's right, [code] and [/code] ...maybe just [/code][/code]

The problem is that a parser can't know the contet of the tags. Is it all one code block? Is it one block with an extra [/code] on the end? Is it two smaller code blocks?

If I just refuse to parse with different numbers, though, then context fails to matter because I just manipulate the stack. All I have to do is make sure the first code tag in the text to be parsed is an open, and the last one is a close, because this could be tragic depending on what context it's printed out in:

[/code]uncoded[code] and leaving the last tag unclosed

Edit: checking to make sure the last one is a [/code] turned out to be unnecessary, all I have to do is make sure I only leave things unparsed if there's a [/code] following the current [code]. One less obstacle, now I just need to worry about my stack.

____________________________
Deploy the... I think it's a yellow button... it's usually flashing... it makes the engines go... WHOOSH!

[Last edited by DiMono at 10-19-2005 07:54 PM]
10-19-2005 at 07:35 PM
View Profile Send Private Message to User Send Email to User Visit Homepage Show all user's posts This architect's holds Quote Reply
DiMono
Level: Smitemaster
Avatar
Rank Points: 1181
Registered: 09-13-2003
IP: Logged
icon Re: The incredible edible programming thread (0)  
So I've managed to code my [code] tags about as well as I think I can. It will only parse a [code] if there is a [/code] somewhere after it. If they're nested I keep track of how deep it is

([code] [code] [/code] [code] [/code] [/code] will be assumed to be one code block that happens to contain [code] [/code] [code] [/code]).

If the nesting isn't valid (i.e. [code] [code] [/code]) it just closes it off at the last [/code] it finds, and if there are trailing [/code] pieces after the nesting is finished (i.e. [code] [/code] [/code]) it extends the selection to the last available [/code] without encountering a [code]. Finally, if there is a trailing [code] with no matching [/code] it's just ignored, because leaving block level elements open never goes well.

After all that, my entire file is a mere 40 lines of code (heh heh) with reasonable room to shrink. Now I just need to decide whether to include lists in my bbcode, which is comparably trivial but still pretty difficult to implement well... seriously, I've spent a total of about 8 hours trying different methods on this [code] thing. And it'll only ever matter if the user says they want bbcode inside a [code] block to go unparsed, which likely won't ever happen. I mean, damn.

Oh, and in retrospect, I think it's better that I didn't do this with regular expressions.

____________________________
Deploy the... I think it's a yellow button... it's usually flashing... it makes the engines go... WHOOSH!
10-20-2005 at 12:54 AM
View Profile Send Private Message to User Send Email to User Visit Homepage Show all user's posts This architect's holds Quote Reply
b0rsuk
Level: Smiter
Avatar
Rank Points: 489
Registered: 11-23-2003
IP: Logged
icon Re: The incredible edible programming thread (+1)  
The best regular expression tutorial I found so far - contains many examples and programs. It has been of great help to me.

Tao of regular expressions

http://sitescooper.org/tao_regexps.html





____________________________

http://www.gamasutra.com/features/20051128/adams_01.shtml
10-20-2005 at 01:18 PM
View Profile Send Private Message to User Send Email to User Show all user's posts Quote Reply
b0rsuk
Level: Smiter
Avatar
Rank Points: 489
Registered: 11-23-2003
IP: Logged
icon Re: The incredible edible programming thread (0)  
(ANSI) C

I use
int zapukaj()
{
    int lock;
    if ((lock = open("lockfile", O_WRONLY | O_CREAT | O_EXCL, 0666)) == -1) {
        return 1;
    } else {
        return 0;
    }
}                               /*koniec funkcji zapukaj */

This function in a pair of primitive client-server programs. I already made such program in Bash, but I wonder... If I use this function in a "while" loop, could it possibly end up with 20 million files open ? I know it's the same file all the time, perhaps I'm just being paranoid. And yeah, C is not my strongest side.
The function tries to check if a file "lockfile" exists. I tested it and it works, but is it safe ?

Which function do I use to close a file ? Is unlink used to delete a file ? Is there a simple way of checking if a file is empty or not ? So many questions, so little time... After using Bash for this, C feels so cumbersome...
=============
By the way: do you know a good online Assembly manual/tutorial ? I found a good page, but it's down for several days now. Trick, perhaps ?

____________________________

http://www.gamasutra.com/features/20051128/adams_01.shtml

[Last edited by b0rsuk at 11-03-2005 12:38 PM]
11-03-2005 at 12:32 PM
View Profile Send Private Message to User Send Email to User Show all user's posts Quote Reply
trick
Level: Legendary Smitemaster
Rank Points: 2580
Registered: 04-12-2003
IP: Logged
icon Re: The incredible edible programming thread (+1)  
b0rsuk wrote:
If I use this function in a "while" loop, could it possibly end up with 20 million files open ?
Not unless you also change the current working directory 20 million times :) (see below).
The function tries to check if a file "lockfile" exists. I tested it and it works, but is it safe ?
Kind of. There's a few issues, though.

First, you don't specify a path to "lockfile", so it will be created/checked for in whatever is the current working directory (cwd). Since there's no restriction what directory you can be in when launching programs, this can be anywhere, unless you set the cwd in the program, of course.

Second, open will do fine on local file systems, but over networked filesystems it may not be an atomic operation, and so may not work properly. The solution is to use link in stead (see the open manpage (man 2 open) under O_EXCL, this is explained there -- you can also look at the DROD source code in DROD/Main.cpp, function IsAppAlreadyRunning(), for an example).

Third, I don't know what you do in the rest of your program, but if you don't delete the lockfile it will have to be deleted manually for subsequent runs. In any case, if the program crashes so that the lockfile isn't deleted, you'll have the same problem. In DROD I solved this by storing the program id (pid) in the lockfile and checking if that pid is running if a lockfile is found (again, you can look at IsAppAlreadyRunning() that I mentioned above for an example). If the pid doesn't exist, the lockfile is invalid, and we can safely continue. This isn't foolproof (the pid may exist but be a different application), but it's much better than nothing. Some sort of IPC would be a better solution, but that would be more complex.

Fourth, you're not closing the lockfile. This isn't the end of the world as having it open throughout the program doesn't affect anything (well, unless you hit the open file limit, which is usually 1024 files), and the OS will close it when the program exits anyway, but I still think you should close it :). In the code snipped above, inserting "close(lock);" right before "return 1;" should do fine.

Which function do I use to close a file ?
close(file). A return value of 0 means it was successful (see man 2 close).
Is unlink used to delete a file ?
Yes :)
Is there a simple way of checking if a file is empty or not ?
Depends what you mean by simple :). There's no "isfileempty" function you can call, but it's pretty easy to use the "stat" function to get the size of the file, and then you can just check if the size is zero. See "man 2 stat".
By the way: do you know a good online Assembly manual/tutorial ? I found a good page, but it's down for several days now. Trick, perhaps ?
I had some very nice links, but I seem to have lost them. I'll see if I can find them again. Anyway, LinuxAssembly.org has some tutorials, but it's not that helpful if you want to do Windows assembly, and I also think most of them assume you're at least a little bit familiar with assembly already (know what a register is and what they're called, basic instructions, etc). Also, NASM has a very nice reference. Their site is down at the moment (seems they missed that SourceForge stopped supporting mysql 3 since the 1st of November..), but archive.org's got it archived here:

http://web.archive.org/web/20041020074845/http://nasm.sourceforge.net/

(The url tag didn't work properly for this one, you need to copy and paste the entire link).

If all else fails, feel free to ask :)

- Gerry
11-03-2005 at 06:13 PM
View Profile Send Private Message to User Send Email to User Show all user's posts Quote Reply
b0rsuk
Level: Smiter
Avatar
Rank Points: 489
Registered: 11-23-2003
IP: Logged
icon Re: The incredible edible programming thread (0)  
trick wrote:
b0rsuk wrote:
If I use this function in a "while" loop, could it possibly end up with 20 million files open ?
Not unless you also change the current working directory 20 million times :) (see below).
That's just what I thought. I suspected it would be a good idea to close it each time (in each iteration)

First, you don't specify a path to "lockfile", so it will be created/checked for in whatever is the current working directory (cwd). Since there's no restriction what directory you can be in when launching programs, this can be anywhere, unless you set the cwd in the program, of course.
I know, but it's the input/output that gives me most trouble in C (well, excluding pointers, and possibly arrays, but shh). I'll paste the "same" program(s) I made in bash.
Oh. Back to topic. I'm going to try one of string.h functions and see if it works. (specification says client should be given username as second parameter)

Second, open will do fine on local file systems, but over networked filesystems (...)
THat would be an overkill. It's meant to be a mockery of client-server app. The theme is threads/processes. But thanks anyway, it may be useful one day.
Third, I don't know what you do in the rest of your program, but if you don't delete the lockfile it will have to be deleted manually for subsequent runs.
Yes, I know what's the purpose of lockfile. If I ask what unlink is for, it is safe to assume I know, right ?
See the bottom of my post for reference. I know what I'm going to do, and I remember a bit from my infamous last year's assignment, but input/output is a bit tricky in C. You typically need several lines/functions per one line of bash.

In any case, if the program crashes so that the lockfile isn't deleted, you'll have the same problem.
Already mentioned at university - we don't need to be pedantic. All I need is basic functionality, proof of concept. This is real concern for serious apps, but not for mock programs.

Is unlink used to delete a file ?
Yes :)
The description in The C Programming Language (by K R) was very muddy. And the name is a little bit confusing.

We're using TASM so far. (linux + xdos emulator). We've been warned about NASM (the GNU one) - the teacher said it has different commands or something like that. Something about compatibility.

Ahem !
----- client
#!/bin/sh
#klient
touch wynik.abc
if [ -z $1 ]
then echo Uruchamiac z parametrem \\<numerek\\>
exit 2
else

dane=`find /home/stud/monuszko/* -name dane.abc 2>/dev/null` # sciezka do dane.abc

if [ -n "$dane" ]
then {
    echo plik z danymi znaleziony
    echo -e $1'\\n'$PWD > $dane # wrzucenie danych i sciezki zwrotnej
        while [ true ]
        do
            if [ -s wynik.abc ]
            then echo Sa wyniki; more wynik.abc
            echo -n > wynik.abc # czysci wynik.abc
            exit 0
            else echo Nie ma wynikow; sleep 3
            fi
        done
        }
else echo Nie znaleziono pliku \\"dane.abc\\"


...and server:
#!/bin/bash
#serwer
touch dane.abc
while [ true ]
    do
       if [ -s dane.abc ] # jest cos w danych ?
         then echo Co my tu mamy ?
         num=`egrep '^[0-9]' dane.abc` # Wczytanie danych
         num=$(((3 * $num) + (2 * ($num * $num)))) # przemielenie danych
         klient=`egrep '^/' dane.abc` # Wczytanie sciezki klienta
         echo $num > $klient/wynik.abc # podrzucenie wyniku
                 echo -n > dane.abc; echo dane.abc wyczyszczony
         else echo na razie nic...
       fi
sleep 3
done


I hope my comments are helpful. The 2 programs run in separate processes, and use 2 text files as buffers. (dane.abc and wynik.abc for data and output). The client puts a number in dane.abc and waits until it's given back.
I used find tool because I'm lazy, not because we were supposed to :D. It's probably not the best programming style, but it worked. Certainly faster than giving full path as first parameter each time. (the fact that C seems to consider the program as first parameter doesn't help to reduce confusion)
Oh, the point is we're supposed to do it again, this time in C and using lockfiles. So I more less know what I'm going to do, but have problems with particulars. Most of the time is spent hunting down missing } and ;.
By the way: This C program is an evidence that B0rsuk eventually learned how to use functions in C.

____________________________

http://www.gamasutra.com/features/20051128/adams_01.shtml
11-03-2005 at 09:09 PM
View Profile Send Private Message to User Send Email to User Show all user's posts Quote Reply
trick
Level: Legendary Smitemaster
Rank Points: 2580
Registered: 04-12-2003
IP: Logged
icon Re: The incredible edible programming thread (0)  
b0rsuk wrote:
Yes, I know what's the purpose of lockfile. If I ask what unlink is for, it is safe to assume I know, right ?
See the bottom of my post for reference.
Sorry if I offended you. You're right, of course. I've been kind of, er, distracted lately.
We're using TASM so far. (linux + xdos emulator). We've been warned about NASM (the GNU one) - the teacher said it has different commands or something like that. Something about compatibility.
For the purposes of being annoyingly pedantic again, NASM isn't a GNU program. It's licensed under a GNU license, but that's not the same thing :). Anyway, you're right there's differences between TASM and NASM, but NASM does have a TASM compatibility mode. ..or were you talking about the GNU assembler, GAS ? I'd stay far away from that thing, if I were you. Assembly gurus have fled crying in terror from its otherworldly, nightmarish syntax.
Ahem !
Ditto.
I hope my comments are helpful.
I'm sure they're helpful to someone that speaks the language. The programs aren't too difficult to understand in any case.
The 2 programs run in separate processes, and use 2 text files as buffers. (dane.abc and wynik.abc for data and output). The client puts a number in dane.abc and waits until it's given back.
I used find tool because I'm lazy, not because we were supposed to :D. It's probably not the best programming style, but it worked. Certainly faster than giving full path as first parameter each time. (the fact that C seems to consider the program as first parameter doesn't help to reduce confusion)
Scripts do the same thing, actually. Tried 'echo $0' ? (The script name doesn't count in $#, though, unlike C's argc).
Oh, the point is we're supposed to do it again, this time in C and using lockfiles. So I more less know what I'm going to do, but have problems with particulars. Most of the time is spent hunting down missing } and ;.
Any particular particulars you want help with ?
By the way: This C program is an evidence that B0rsuk eventually learned how to use functions in C.
Congratulations :)

- Gerry
11-03-2005 at 10:06 PM
View Profile Send Private Message to User Send Email to User Show all user's posts Quote Reply
b0rsuk
Level: Smiter
Avatar
Rank Points: 489
Registered: 11-23-2003
IP: Logged
icon Re: The incredible edible programming thread (0)  
How do I get current working directory ? There's a getcwd function in GNU C library, but I'd prefer not to use it unless there's no other way.

At least I managed to use chdir sucessfuly. The problem is that I will probably need to switch the working directory back and forth. I may be exaggerating a bit, but I need to destroy the lockfile later.

I mean.. I'm not sure if simply remove or unlink (lock) will work after changing working directory. I'll have to check.

____________________________

http://www.gamasutra.com/features/20051128/adams_01.shtml

[Last edited by b0rsuk at 11-04-2005 12:16 PM]
11-04-2005 at 12:05 PM
View Profile Send Private Message to User Send Email to User Show all user's posts Quote Reply
trick
Level: Legendary Smitemaster
Rank Points: 2580
Registered: 04-12-2003
IP: Logged
icon Re: The incredible edible programming thread (0)  
b0rsuk wrote:
How do I get current working directory ? There's a getcwd function in GNU C library, but I'd prefer not to use it unless there's no other way.
Why not ? Is it because you have to preallocate memory to contain the directory name ? Linux allows you to pass a NULL pointer to getcwd to have it allocate the memory for you, but this isn't portable (passing a NULL pointer to getcwd is generally undefined). There is a function called "get_current_dir_name" that mallocs the memory for you and returns the direcory, but this is a GNU extension, so you probably can't use it in your example program.

You can also read the PWD environment variable, which gets set by most shells. However, this is not guaranteed to be set at all, and even if it is set it might be set to a different path, or something else.

In Linux, another option is see what the symlink /proc/self/cwd points to (readlink, etc), but this is of course not even remotely portable.

In any case, if you just need to pass the current directory as an argument to some function, you can use "." (I expect you already knew this, but hey).
At least I managed to use chdir sucessfuly. The problem is that I will probably need to switch the working directory back and forth. I may be exaggerating a bit, but I need to destroy the lockfile later.
Are you sure you need to change the working directory ? Adding some paths to the files you want to access might be a better option.
I mean.. I'm not sure if simply remove or unlink (lock) will work after changing working directory. I'll have to check.
Not unless you give a valid path. Relative paths (ie all paths not starting with "/" (or, in windows, a drive, etc)) are relative to the current directory, so if you change the current directory, all relative paths point somewhere else.

- Gerry
11-05-2005 at 07:41 PM
View Profile Send Private Message to User Send Email to User Show all user's posts Quote Reply
b0rsuk
Level: Smiter
Avatar
Rank Points: 489
Registered: 11-23-2003
IP: Logged
icon Re: The incredible edible programming thread (0)  
trick wrote:
b0rsuk wrote:
How do I get current working directory ? There's a getcwd function in GNU C library, but I'd prefer not to use it unless there's no other way.
Why not ? Is it because you have to preallocate memory to contain the directory name ?

Portability may be one reason, paranoia another. And the third - B0rsuk may act pedantic when you least expect it.

In any case, if you just need to pass the current directory as an argument to some function, you can use "." (I expect you already knew this, but hey).
Are you sure it works in C ? I know it works in bash, but... hmm.

Are you sure you need to change the working directory ? Adding some paths to the files you want to access might be a better option.
It would be a better option if it worked for me. I tried and failed. But if you say it's actually possible...
I tried something like open(pathvariable, blah | BLAH | blah | BLAH); etc.
where pathvariable was something like char [20] or similar, containing stuff like /home/zaocz/username.
I tried using strncat to cat argv[1] into pathvariable, but it gave me some weird compilation errors, and I ran away screaming.



____________________________

http://www.gamasutra.com/features/20051128/adams_01.shtml

[Last edited by b0rsuk at 11-05-2005 08:03 PM]
11-05-2005 at 08:00 PM
View Profile Send Private Message to User Send Email to User Show all user's posts Quote Reply
trick
Level: Legendary Smitemaster
Rank Points: 2580
Registered: 04-12-2003
IP: Logged
icon Re: The incredible edible programming thread (+1)  
b0rsuk wrote:
Portability may be one reason, paranoia another. And the third - B0rsuk may act pedantic when you least expect it.
If you want portability, you should use getcwd (without the NULL pointer trick). It's a standard POSIX function.

In any case, if you just need to pass the current directory as an argument to some function, you can use "." (I expect you already knew this, but hey).
Are you sure it works in C ? I know it works in bash, but... hmm.
Yes, I'm sure. Parent dir ("..") works too. These things are a property of the file system (or the OS), not the language, so they work regardless of what language you use. It even works in Windows.

Are you sure you need to change the working directory ? Adding some paths to the files you want to access might be a better option.
It would be a better option if it worked for me. I tried and failed. But if you say it's actually possible...
I tried something like open(pathvariable, blah | BLAH | blah | BLAH); etc.
where pathvariable was something like char [20] or similar, containing stuff like /home/zaocz/username.
I tried using strncat to cat argv[1] into pathvariable, but it gave me some weird compilation errors, and I ran away screaming.
If pathvariable is allocated as char[20] and you put "/home/zaocz/username" in it, if username is at least 7 chars then the array is full. If username is 8 chars or more, it's more than full (remember the terminating 0), so you've already got a potential segfault there. strcat'ing more things after that will only make things worse. strncat won't have room to add anything, assuming you set the length parameter right. Make more room!

- Gerry
11-07-2005 at 10:07 PM
View Profile Send Private Message to User Send Email to User Show all user's posts Quote Reply
b0rsuk
Level: Smiter
Avatar
Rank Points: 489
Registered: 11-23-2003
IP: Logged
icon Re: The incredible edible programming thread (0)  
So I'm lost again.

I use a function to create lockfile. The function tries to take a string as a parameter, cat "lockfile" at the end of it (I managed to successfuly do so before) and create a lockfile in path essentially defined by argv[1].
I don't know how to nail the bug down. Lines "40something" are in definition of the function; 25 - in main. It worked up to the point where I need to use the function.

cclient.c:44: warning: type mismatch with previous implicit declaration
cclient.c:25: warning: previous implicit declaration of `zapukaj'
cclient.c: In function `zapukaj':
cclient.c:46: warning: passing arg 1 of `strlen' makes pointer from integer without a cast
cclient.c:47: warning: passing arg 2 of `strcat' makes pointer from integer without a cast

From main:
char sciezka[strlen(argv[1]+12)]; /* 12 bo /home/zaocz/ ma tyle */
strcat(sciezka, "/home/zaocz/");
strcat(sciezka, argv[1]);
printf("Test - %s \\n", sciezka);


Function declared after main:
int zapukaj(char gdzie)
{

char plik[strlen(gdzie) + 8]; /* 8 za lockfile */
strcat(plik, gdzie);
strcat(plik, "lockfile");

    int lock;
    if ((lock = open(plik, O_WRONLY | O_CREAT | O_EXCL, 0666)) == -1) {
        return 1;
    } else {
        return 0;
    }
}                               /*koniec funkcji zapukaj */


What am I doing wrong ?

____________________________

http://www.gamasutra.com/features/20051128/adams_01.shtml

[Last edited by b0rsuk at 11-08-2005 01:49 PM]
11-08-2005 at 01:46 PM
View Profile Send Private Message to User Send Email to User Show all user's posts Quote Reply
Maurog
Level: Smitemaster
Avatar
Rank Points: 1501
Registered: 09-16-2004
IP: Logged
icon Re: The incredible edible programming thread (0)  
From first glance: gdzie should be a char* instead of char if I know anything about strcat.

____________________________
Slay the living! Raise the dead!
Paint the sky in crimson red!
11-08-2005 at 01:55 PM
View Profile Send Private Message to User Send Email to User Show all user's posts Quote Reply
trick
Level: Legendary Smitemaster
Rank Points: 2580
Registered: 04-12-2003
IP: Logged
icon Re: The incredible edible programming thread (0)  
Maurog wrote:
From first glance: gdzie should be a char* instead of char if I know anything about strcat.
What he said. Also, you might want to insert a prototype of zapukaj to somewhere before it's called the first time, so that you avoid implicit declarations.

- Gerry
11-08-2005 at 08:57 PM
View Profile Send Private Message to User Send Email to User Show all user's posts Quote Reply
MartianInvader
Level: Master Delver
Rank Points: 126
Registered: 01-30-2004
IP: Logged
icon Re: The incredible edible programming thread (+1)  
Also, that first line of main looks to have a typo: I'm pretty sure you want that "+12" outside of the strlen call. The way you have it you're allocating something with 12 fewer characters than your second argument instead of 12 more, which will can get you segfault troubles when you try to strcat in more than you've allocated.

____________________________
Yes, I very rarely post. But I DO keep coming back to check the forum.
11-09-2005 at 02:25 AM
View Profile Send Private Message to User Show all user's posts Quote Reply
trick
Level: Legendary Smitemaster
Rank Points: 2580
Registered: 04-12-2003
IP: Logged
icon Re: The incredible edible programming thread (0)  
Yes. Also, you need to add 1 more to both of the string allocations, to account for the terminating zero (eg strlen("abc") returns 3, but the string "abc" requires 3 bytes for the string and 1 for the terminating zero, ie 4 bytes). Also, the first of the two strcat's after the allocations (both in main and in zapukaj) will probably fail because the allocated memory hasn't been initialized (ie it's an undefined string of undefined length, so the strcat could start cating the string anywhere). Change the first of the strcats to strcpy to fix this.

Btw, don't feel bad about all these little mistakes, we've all done them when starting out :)

- Gerry
11-09-2005 at 04:30 AM
View Profile Send Private Message to User Send Email to User Show all user's posts Quote Reply
b0rsuk
Level: Smiter
Avatar
Rank Points: 489
Registered: 11-23-2003
IP: Logged
icon Re: The incredible edible programming thread (0)  
You make me feel the worst coder on this forum, and that's including people who don't code.

Is there any "pointers/casts for dummies"-like tutorial anywhere ? Because I clearly didn't understand it right first time.
EDIT
Ok, I can google for myself. Nevermind.

Now it works, sort of, but I have some weird problem. Somehow the leading zero doesn't complain about having no place to be. Not even -ANSI -pedantic -Wall gives any warnings. There are other warnings, of course, but shhh.

The mystery:

"/home/zaocz/monuszko/lockfile" (brute-forced string) doesn't equal the one created by strcpy and strcat. Even if it looks same to me. I used printf for debug. I suspect the "end of string" character is guilty. How do I fix that ? The lockfile isn't created.

Another issue... My function prints same message "Zajete!" no matter if it can't create lockfile because of wrong directory (parameter) given, or because a lockfile already exists. Can I do it some smart way, or do I need a separate function for that ? THat would suck. And I would have to remove the test file later, I think.

The part before "if ... open" is unnecessarily big because of debug reasons.


int zapukaj(char *gdzie)
{

char plik[strlen(gdzie) + 9]; /* 9 za /lockfile */
strcpy(plik, gdzie);
strcat(plik, "/lockfile");
printf("Plik: %s \\n", plik);
if (strcmp(plik, "/home/zaocz/monuszko/lockfile") == 0)
printf("Same \\n");
else printf("Differs \\n");


int lock;
if ((lock = open(plik, O_WRONLY | O_CREAT | O_EXCL, 0666)) == -1) {
return 1;
} else {
return 0;
}
} /*koniec funkcji zapukaj */


strcmp prints "Differs", even if I give my login (monuszko) as parameter.

____________________________

http://www.gamasutra.com/features/20051128/adams_01.shtml

[Last edited by b0rsuk at 11-09-2005 12:35 PM]
11-09-2005 at 08:15 AM
View Profile Send Private Message to User Send Email to User Show all user's posts Quote Reply
trick
Level: Legendary Smitemaster
Rank Points: 2580
Registered: 04-12-2003
IP: Logged
icon Re: The incredible edible programming thread (+1)  
b0rsuk wrote:
You make me feel the worst coder on this forum, and that's including people who don't code.
Hey, I was serious when I said you shouldn't feel bad about it. You're learning C for the first time, a language full of little subtleties that is easy to miss. It's just natural to do a couple mistakes. The important thing is that you learn from the mistakes you make :)

Is there any "pointers/casts for dummies"-like tutorial anywhere ? Because I clearly didn't understand it right first time.
I could write something up for you, if you want.
char plik[strlen(gdzie) + 9]; /* 9 za /lockfile */
You didn't allow space for the terminating zero. Replace this with:
char plik[strlen(gdzie) + 10]; /* 9 za /lockfile, +1 za \\0 */

Look, I pretended to know polish! Whee.

Anyway, unless the terminating zero character outside the plik array is immediately overwritten by something else (unlikely, but possible), the strcmp shouldn't actually be affected by this bug (other than a possible segfault, but in that case the strcat would have segfaulted already). Are you sure you're passing the right string to the zapukaj function ? No extra slashes or anything ?

Also, the "int lock;" declaration that appears later in the function is illegal ANSI C (although this is legal in C99). Move it to the top of the function to avoid warnings about that.

- Gerry

Edit: In other news, this was my post #1234. Go me.

[Last edited by trick at 11-09-2005 03:28 PM]
11-09-2005 at 03:19 PM
View Profile Send Private Message to User Send Email to User Show all user's posts Quote Reply
b0rsuk
Level: Smiter
Avatar
Rank Points: 489
Registered: 11-23-2003
IP: Logged
icon Re: The incredible edible programming thread (0)  
It didn't solve my problem.

printf("%s",plik); /* prints this: */
/home/zaocz/monuszko/lockfile
(pasted)

The string I compare to is:
/home/zaocz/monuszko/lockfile

Looks exactly the same for me. If there's any difference, it's some kind of invisible character.

if (strcmp(plik, "/home/zaocz/monuszko/lockfile") == 0)
printf("Same \\n");
else printf("Differs \\n");


EDIT:
Seems like I'll have to go back to chdir. At least it worked for me.

____________________________

http://www.gamasutra.com/features/20051128/adams_01.shtml

[Last edited by b0rsuk at 11-10-2005 10:49 AM]
11-10-2005 at 10:48 AM
View Profile Send Private Message to User Send Email to User Show all user's posts Quote Reply
trick
Level: Legendary Smitemaster
Rank Points: 2580
Registered: 04-12-2003
IP: Logged
icon Re: The incredible edible programming thread (+1)  
b0rsuk wrote:
It didn't solve my problem.

printf("%s",plik); /* prints this: */
/home/zaocz/monuszko/lockfile
(pasted)

The string I compare to is:
/home/zaocz/monuszko/lockfile

Looks exactly the same for me. If there's any difference, it's some kind of invisible character.
Yeah. You could try printing both strings with this little function to see what's going on:
void hexdump (const char *s)
{
    do printf("%02x ", *s);
    while (*(s++));
    printf("\\n");
}

Seems like I'll have to go back to chdir. At least it worked for me.
If that works, sure.

- Gerry
11-10-2005 at 11:49 PM
View Profile Send Private Message to User Send Email to User Show all user's posts Quote Reply
b0rsuk
Level: Smiter
Avatar
Rank Points: 489
Registered: 11-23-2003
IP: Logged
icon Re: The incredible edible programming thread (0)  
The function you listed proved helpful (seems like). The first string (contents of "plik" variable) has one more character at the beginning. All other are the same.

The extra character has code 02. If I read the ascii table correctly, 02 hex = "start of text" character. That would explain a lot.

I'll try to remove the first character from string somehow and see if it works.
By the way, why... nevermind. I can't count.

WAIT A SECOND !!!
The hexdump function you gave me prints 02 character by definition. Why ?
Otherwise, the two strings are identical. So what could it be ?

____________________________

http://www.gamasutra.com/features/20051128/adams_01.shtml

[Last edited by b0rsuk at 11-11-2005 04:03 PM]
11-11-2005 at 03:10 PM
View Profile Send Private Message to User Send Email to User Show all user's posts Quote Reply
Page 1 of 2
2
New Topic New Poll Post Reply
Caravel Forum : Other Boards : Anything : The incredible edible programming thread
Surf To:


Forum Rules:
Can I post a new topic? No
Can I reply? No
Can I read? Yes
HTML Enabled? No
UBBC Enabled? Yes
Words Filter Enable? No

Contact Us | CaravelGames.com

Powered by: tForum tForumHacks Edition b0.98.8
Originally created by Toan Huynh (Copyright © 2000)
Enhanced by the tForumHacks team and the Caravel team.