Freeswitch-svn
Threads by month
- ----- 2026 -----
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
November 2007
- 10 participants
- 328 discussions
Author: brian
Date: Wed Nov 14 16:13:26 2007
New Revision: 6265
Added:
freeswitch/trunk/conf/lang/de/vm/
Log:
more to come
1
0
[commit] r6264 - in freeswitch/trunk/conf: . lang/en lang/en/demo lang/en/vm
by Freeswitch SVN 14 Nov '07
by Freeswitch SVN 14 Nov '07
14 Nov '07
Author: anthm
Date: Wed Nov 14 16:11:54 2007
New Revision: 6264
Added:
freeswitch/trunk/conf/lang/en/demo/
freeswitch/trunk/conf/lang/en/demo/demo.xml
freeswitch/trunk/conf/lang/en/en.xml
freeswitch/trunk/conf/lang/en/vm/
freeswitch/trunk/conf/lang/en/vm/sounds.xml
freeswitch/trunk/conf/lang/en/vm/tts.xml
Removed:
freeswitch/trunk/conf/lang_en.xml
freeswitch/trunk/conf/voicemail_en.xml
freeswitch/trunk/conf/voicemail_en_tts.xml
Modified:
freeswitch/trunk/conf/freeswitch.xml
Log:
mess with config
Modified: freeswitch/trunk/conf/freeswitch.xml
==============================================================================
--- freeswitch/trunk/conf/freeswitch.xml (original)
+++ freeswitch/trunk/conf/freeswitch.xml Wed Nov 14 16:11:54 2007
@@ -107,14 +107,7 @@
<!-- phrases section (under development still) -->
<section name="phrases" description="Speech Phrase Management">
<macros>
- <language name="en" sound-path="/snds" tts-engine="cepstral" tts-voice="david">
- <X-PRE-PROCESS cmd="include" data="lang_en.xml"/>
- <!--voicemail_en_tts is purely implemented with tts, we need a files based implementation too -->
- <X-PRE-PROCESS cmd="include" data="voicemail_en_tts.xml"/>
- </language>
- <language name="fr" sound_path="/var/sounds/lang/fr/jean" tts_engine="cepstral" tts_voice="jean-pierre">
- <X-PRE-PROCESS cmd="include" data="lang_fr.xml"/>
- </language>
+ <X-PRE-PROCESS cmd="include" data="lang/*/*.xml"/>
</macros>
</section>
Added: freeswitch/trunk/conf/lang/en/demo/demo.xml
==============================================================================
--- (empty file)
+++ freeswitch/trunk/conf/lang/en/demo/demo.xml Wed Nov 14 16:11:54 2007
@@ -0,0 +1,71 @@
+<include><!--This line will be ignored it's here to validate the xml and is optional -->
+ <macro name="msgcount">
+ <input pattern="(.*)">
+ <match>
+ <action function="execute" data="sleep(1000)"/>
+ <action function="play-file" data="vm-youhave.wav"/>
+ <action function="say" data="$1" method="pronounced" type="items"/>
+ <action function="play-file" data="vm-messages.wav"/>
+ <!-- or -->
+ <!--<action function="speak-text" data="you have $1 messages"/>-->
+ </match>
+ </input>
+ </macro>
+ <macro name="saydate">
+ <input pattern="(.*)">
+ <match>
+ <action function="say" data="$1" method="pronounced" type="current_date_time"/>
+ </match>
+ </input>
+ </macro>
+ <macro name="timespec">
+ <input pattern="(.*)">
+ <match>
+ <action function="say" data="$1" method="pronounced" type="time_measurement"/>
+ </match>
+ </input>
+ </macro>
+ <macro name="ip-addr">
+ <input pattern="(.*)">
+ <match>
+ <action function="say" data="$1" method="iterated" type="ip_address"/>
+ <action function="say" data="$1" method="pronounced" type="ip_address"/>
+ </match>
+ </input>
+ </macro>
+ <macro name="spell">
+ <input pattern="(.*)">
+ <match>
+ <action function="say" data="$1" method="pronounced" type="name_spelled"/>
+ </match>
+ </input>
+ </macro>
+ <macro name="spell-phonetic">
+ <input pattern="(.*)">
+ <match>
+ <action function="say" data="$1" method="pronounced" type="name_phonetic"/>
+ </match>
+ </input>
+ </macro>
+ <macro name="tts-timeleft">
+ <!-- The parser will visit each <input> tag and execute the actions in <match> or <nomatch> depending on the pattern param -->
+ <!-- If the function "break" is encountered all parsing will cease -->
+ <input pattern="(\d+):(\d+)">
+ <match>
+ <action function="speak-text" data="You have $1 minutes, $2 seconds remaining $strftime(%Y-%m-%d)"/>
+ <action function="break"/>
+ </match>
+ <nomatch>
+ <action function="speak-text" data="That input was invalid."/>
+ </nomatch>
+ </input>
+ <input pattern="(\d+) min (\d+) sec">
+ <match>
+ <action function="speak-text" data="You have $1 minutes, $2 seconds remaining $strftime(%Y-%m-%d)"/>
+ </match>
+ <nomatch>
+ <action function="speak-text" data="That input was invalid."/>
+ </nomatch>
+ </input>
+ </macro>
+</include><!--This line will be ignored it's here to validate the xml and is optional -->
Added: freeswitch/trunk/conf/lang/en/en.xml
==============================================================================
--- (empty file)
+++ freeswitch/trunk/conf/lang/en/en.xml Wed Nov 14 16:11:54 2007
@@ -0,0 +1,7 @@
+<include>
+ <language name="en" sound-path="/snds" tts-engine="cepstral" tts-voice="david">
+ <X-PRE-PROCESS cmd="include" data="demo/demo.xml"/>
+ <!--voicemail_en_tts is purely implemented with tts, we need a files based implementation too -->
+ <X-PRE-PROCESS cmd="include" data="vm/tts.xml"/>
+ </language>
+</include>
Added: freeswitch/trunk/conf/lang/en/vm/sounds.xml
==============================================================================
--- (empty file)
+++ freeswitch/trunk/conf/lang/en/vm/sounds.xml Wed Nov 14 16:11:54 2007
@@ -0,0 +1,273 @@
+<include><!--This line will be ignored it's here to validate the xml and is optional -->
+ <macro name="voicemail_enter_id">
+ <input pattern="(.*)">
+ <match>
+ <action function="play-file" data="voicemail/vm-enter_id.wav"/>
+ <action function="say" data="$1" method="pronounced" type="items"/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_enter_pass">
+ <input pattern="(.*)">
+ <match>
+ <action function="play-file" data="voicemail/vm-enter_pass.wav"/>
+ <action function="say" data="$1" method="pronounced" type="items"/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_fail_auth">
+ <input pattern="(.*)">
+ <match>
+ <action function="play-file" data="voicemail/vm-fail_auth.wav"/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_hello">
+ <input pattern="(.*)">
+ <match>
+ <action function="play-file" data="voicemail/vm-hello.wav"/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_goodbye">
+ <input pattern="(.*)">
+ <match>
+ <action function="play-file" data="voicemail/vm-goodbye.wav"/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_abort">
+ <input pattern="(.*)">
+ <match>
+ <action function="play-file" data="voicemail/vm-abort.wav"/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_message_count">
+ <input pattern="^1:(.*)$">
+ <match>
+ <action function="play-file" data="voicemail/vm-you_have.wav"/>
+ <action function="say" data="1" method="pronounced" type="items"/>
+ <action function="play-file" data="voicemail/vm-$1.wav"/>
+ <action function="play-file" data="voicemail/vm-message.wav"/>
+ <action function="play-file" data="voicemail/vm-in_folder.wav"/>
+ </match>
+ </input>
+ <input pattern="^([0,2-9]+):(.*)$">
+ <match>
+ <action function="play-file" data="voicemail/vm-you_have.wav"/>
+ <action function="say" data="$1" method="pronounced" type="items"/>
+ <action function="play-file" data="voicemail/vm-$1.wav"/>
+ <action function="play-file" data="voicemail/vm-messages.wav"/>
+ <action function="play-file" data="voicemail/vm-in_folder.wav"/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_menu">
+ <input pattern="^([0-9#*]):([0-9#*]):([0-9#*]):([0-9#*])$">
+ <match>
+ <action function="play-file" data="voicemail/vm-press.wav"/>
+ <action function="say" data="$1" method="pronounced" type="name_spelled"/>
+ <action function="play-file" data="voicemail/vm-listen_new.wav"/>
+ <action function="play-file" data="voicemail/vm-press.wav"/>
+ <action function="say" data="$2" method="pronounced" type="name_spelled"/>
+ <action function="play-file" data="voicemail/vm-listen_saved.wav"/>
+ <action function="play-file" data="voicemail/vm-press.wav"/>
+ <action function="say" data="$3" method="pronounced" type="name_spelled"/>
+ <action function="play-file" data="voicemail/vm-advanced.wav"/>
+ <action function="say" data="$4" method="pronounced" type="name_phonetic"/>
+ <action function="play-file" data="voicemail/vm-to_exit.wav"/>
+ </match>
+ </input>
+ </macro>
+
+
+ <macro name="voicemail_config_menu">
+ <input pattern="^([0-9#*]):([0-9#*]):([0-9#*]):([0-9#*])$">
+ <match>
+ <action function="play-file" data="voicemail/vm-press.wav"/>
+ <action function="say" data="$1" method="pronounced" type="name_spelled"/>
+ <action function="play-file" data="voicemail/vm-record_greeting.wav"/>
+ <action function="play-file" data="voicemail/vm-press.wav"/>
+ <action function="say" data="$2" method="pronounced" type="name_spelled"/>
+ <action function="play-file" data="voicemail/vm-choose_greeting.wav"/>
+ <action function="play-file" data="voicemail/vm-press.wav"/>
+ <action function="say" data="$3" method="pronounced" type="name_spelled"/>
+ <action function="play-file" data="voicemail/vm-record_name2.wav"/>
+ <action function="play-file" data="voicemail/vm-press.wav"/>
+ <action function="say" data="$4" method="pronounced" type="name_spelled"/>
+ <action function="play-file" data="voicemail/vm-main_menu.wav"/>
+ </match>
+ </input>
+ </macro>
+
+
+ <macro name="voicemail_record_name">
+ <input pattern="^(.*)$">
+ <match>
+ <action function="play-file" data="voicemail/vm-record_name1.wav"/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_record_file_check">
+ <input pattern="^([0-9#*]):([0-9#*]):([0-9#*])$">
+ <match>
+ <action function="play-file" data="voicemail/vm-press.wav"/>
+ <action function="say" data="$1" method="pronounced" type="name_spelled"/>
+ <action function="play-file" data="voicemail/vm-listen_to_recording.wav"/>
+ <action function="play-file" data="voicemail/vm-press.wav"/>
+ <action function="say" data="$2" method="pronounced" type="name_spelled"/>
+ <action function="play-file" data="voicemail/vm-save_recording.wav"/>
+ <action function="play-file" data="voicemail/vm-press.wav"/>
+ <action function="say" data="$3" method="pronounced" type="name_spelled"/>
+ <action function="play-file" data="voicemail/vm-rerecord.wav"/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_record_urgent_check">
+ <input pattern="^([0-9#*]):([0-9#*])$">
+ <match>
+ <action function="play-file" data="voicemail/vm-mark_urgent.wav"/>
+ <action function="play-file" data="voicemail/vm-press.wav"/>
+ <action function="say" data="$1" method="pronounced" type="name_spelled"/>
+ <action function="play-file" data="voicemail/vm-continue.wav"/>
+ <action function="play-file" data="voicemail/vm-press.wav"/>
+ <action function="say" data="$2" method="pronounced" type="name_spelled"/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_listen_file_check">
+ <input pattern="^([0-9#*]):([0-9#*]):([0-9#*]):([0-9#*])$">
+ <match>
+ <action function="play-file" data="voicemail/vm-press.wav"/>
+ <action function="say" data="$1" method="pronounced" type="name_spelled"/>
+ <action function="play-file" data="voicemail/vm-listen_to_recording.wav"/>
+ <action function="play-file" data="voicemail/vm-press.wav"/>
+ <action function="say" data="$2" method="pronounced" type="name_spelled"/>
+ <action function="play-file" data="voicemail/vm-save_recording.wav"/>
+ <action function="play-file" data="voicemail/vm-press.wav"/>
+ <action function="say" data="$3" method="pronounced" type="name_spelled"/>
+ <action function="play-file" data="voicemail/vm-delete_recording.wav"/>
+ <action function="play-file" data="voicemail/vm-press.wav"/>
+ <action function="say" data="$4" method="pronounced" type="name_spelled"/>
+ <action function="play-file" data="voicemail/vm-forward_to_email.wav"/>
+ <action function="play-file" data="voicemail/vm-press.wav"/>
+ <action function="say" data="$4" method="pronounced" type="name_spelled"/>
+ <action function="play-file" data="voicemail/vm-return_call.wav"/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_choose_greeting">
+ <input pattern="^(.*)$">
+ <match>
+ <action function="play-file" data="voicemail/vm-choose_greeting.wav"/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_choose_greeting_fail">
+ <input pattern="^(.*)$">
+ <match>
+ <action function="play-file" data="voicemail/vm-choose_greeting_fail.wav"/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_record_greeting">
+ <input pattern="^(.*)$">
+ <match>
+ <action function="play-file" data="voicemail/vm-record_greeting.wav"/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_record_message">
+ <input pattern="^(.*)$">
+ <match>
+ <action function="play-file" data="voicemail/vm-record_message.wav"/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_greeting_selected">
+ <input pattern="^(.*)$">
+ <match>
+ <action function="play-file" data="voicemail/vm-greeting.wav"/>
+ <action function="say" data="$1" method="pronounced" type="items"/>
+ <action function="play-file" data="voicemail/vm-selected.wav"/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_play_greeting">
+ <input pattern="^(.*)$">
+ <match>
+ <action function="say" data="$1" method="pronounced" type="name_spelled"/>
+ <action function="play-file" data="voicemail/vm-not_avaliable.wav"/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_say_number">
+ <input pattern="^(.*)$">
+ <match>
+ <action function="say" data="$1" method="pronounced" type="items"/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_say_message_number">
+ <input pattern="^([a-z]+):(.*)$">
+ <match>
+ <action function="play-file" data="voicemail/vm-$1.wav"/>
+ <action function="play-file" data="voicemail/vm-message_number.wav"/>
+ <action function="say" data="$2" method="pronounced" type="items"/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_say_phone_number">
+ <input pattern="^(.*)$">
+ <match>
+ <action function="say" data="$1" method="pronounced" type="name_spelled"/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_say_name">
+ <input pattern="^(.*)$">
+ <match>
+ <action function="say" data="$1" method="pronounced" type="name_spelled"/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_ack">
+ <input pattern="^(.*)$">
+ <match>
+ <action function="play-file" data="voicemail/vm-message.wav"/>
+ <action function="play-file" data="voicemail/vm-$1.wav"/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_say_date">
+ <input pattern="^(.*)$">
+ <match>
+ <action function="say" data="$strftime($1|%A, %B %d %Y, %I %M %p)" method="pronounced" type="current_date_time"/>
+ </match>
+ </input>
+ </macro>
+
+</include><!--This line will be ignored it's here to validate the xml and is optional -->
Added: freeswitch/trunk/conf/lang/en/vm/tts.xml
==============================================================================
--- (empty file)
+++ freeswitch/trunk/conf/lang/en/vm/tts.xml Wed Nov 14 16:11:54 2007
@@ -0,0 +1,215 @@
+<include><!--This line will be ignored it's here to validate the xml and is optional -->
+ <macro name="voicemail_enter_id">
+ <input pattern="(.*)">
+ <match>
+ <action function="speak-text" data="please enter your i d, followed by $1."/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_enter_pass">
+ <input pattern="(.*)">
+ <match>
+ <action function="speak-text" data="please enter your password, followed by $1."/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_fail_auth">
+ <input pattern="(.*)">
+ <match>
+ <action function="speak-text" data="login incorrect."/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_hello">
+ <input pattern="(.*)">
+ <match>
+ <action function="speak-text" data="welcome to your voicemail."/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_goodbye">
+ <input pattern="(.*)">
+ <match>
+ <action function="speak-text" data="goodbye."/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_abort">
+ <input pattern="(.*)">
+ <match>
+ <action function="speak-text" data="too many failed attempts."/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_message_count">
+ <input pattern="^1:(.*)$">
+ <match>
+ <action function="speak-text" data="you have 1 $1 message in folder ${voicemail_current_folder}."/>
+ </match>
+ </input>
+ <input pattern="^([0,2-9]+):(.*)$">
+ <match>
+ <action function="speak-text" data="you have $1 $2 messages in folder ${voicemail_current_folder}."/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_menu">
+ <input pattern="^([0-9#*]):([0-9#*]):([0-9#*]):([0-9#*])$">
+ <match>
+ <action function="speak-text"
+ data="To listen to new messages, press $1, To listen to saved messages, press $2, For advanced options, press $3, to exit, press $4."/>
+ </match>
+ </input>
+ </macro>
+
+
+ <macro name="voicemail_config_menu">
+ <input pattern="^([0-9#*]):([0-9#*]):([0-9#*]):([0-9#*])$">
+ <match>
+ <action function="speak-text"
+ data="To record a greeting, press $1, To choose a greeting, press $2, To record your name, press $3, to return to the main menu, press $4."/>
+ </match>
+ </input>
+ </macro>
+
+
+ <macro name="voicemail_record_name">
+ <input pattern="^(.*)$">
+ <match>
+ <action function="speak-text" data="at the tone, record your name, press any key or stop talking to end the recording."/>
+
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_record_file_check">
+ <input pattern="^([0-9#*]):([0-9#*]):([0-9#*])$">
+ <match>
+ <action function="speak-text"
+ data="To listen to the recording, press $1, To save the recording, press $2, To re record, press $3."/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_record_urgent_check">
+ <input pattern="^([0-9#*]):([0-9#*])$">
+ <match>
+ <action function="speak-text"
+ data="To mark this message urgent, press $1, To continue, press $2."/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_listen_file_check">
+ <input pattern="^([0-9#*]):([0-9#*]):([0-9#*]):([0-9#*]):([0-9#*])$">
+ <match>
+ <action function="speak-text"
+ data="To listen to the recording again, press $1, To save the recording, press $2, To delete the recording, press $3, to forward the recording to your email, press $4, to call the caller now, press $5."/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_choose_greeting">
+ <input pattern="^(.*)$">
+ <match>
+ <action function="speak-text" data="choose a greeting between 1 and 3."/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_choose_greeting_fail">
+ <input pattern="^(.*)$">
+ <match>
+ <action function="speak-text" data="invalid value."/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_record_greeting">
+ <input pattern="^(.*)$">
+ <match>
+ <action function="speak-text" data="record your greeting at the tone, press any key or stop talking to end the recording."/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_record_message">
+ <input pattern="^(.*)$">
+ <match>
+ <action function="speak-text" data="record your message at the tone, press any key or stop talking to end the recording."/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_greeting_selected">
+ <input pattern="^(.*)$">
+ <match>
+ <action function="speak-text" data="greeting $1 selected."/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_play_greeting">
+ <input pattern="^(.*)$">
+ <match>
+ <action function="speak-text" data="$1 is not available."/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_say_number">
+ <input pattern="^(.*)$">
+ <match>
+ <action function="speak-text" data="$1"/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_say_message_number">
+ <input pattern="^([a-z]+):(.*)$">
+ <match>
+ <action function="speak-text" data="$1 message number $2."/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_say_phone_number">
+ <input pattern="^(.*)$">
+ <match>
+ <action function="speak-text" data="$1."/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_say_name">
+ <input pattern="^(.*)$">
+ <match>
+ <action function="speak-text" data="$1."/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_ack">
+ <input pattern="^(.*)$">
+ <match>
+ <action function="speak-text" data="message $1"/>
+ </match>
+ </input>
+ </macro>
+
+ <macro name="voicemail_say_date">
+ <input pattern="^(.*)$">
+ <match>
+ <action function="speak-text" data="${strftime($1|%A, %B %d %Y, %I:%M %p)}"/>
+ </match>
+ </input>
+ </macro>
+
+</include><!--This line will be ignored it's here to validate the xml and is optional -->
1
0
Author: anthm
Date: Wed Nov 14 16:08:21 2007
New Revision: 6263
Modified:
freeswitch/trunk/src/switch_xml.cpp
Log:
don't delete fsxml files
Modified: freeswitch/trunk/src/switch_xml.cpp
==============================================================================
--- freeswitch/trunk/src/switch_xml.cpp (original)
+++ freeswitch/trunk/src/switch_xml.cpp Wed Nov 14 16:08:21 2007
@@ -1694,7 +1694,9 @@
}
if (xml->free_path) {
- unlink(xml->free_path);
+ if (!switch_stristr(xml->free_path, ".fsxml")) {
+ unlink(xml->free_path);
+ }
switch_safe_free(xml->free_path);
}
1
0
Author: anthm
Date: Wed Nov 14 16:01:15 2007
New Revision: 6262
Modified:
freeswitch/trunk/src/switch_xml.cpp
Log:
relative path in include
Modified: freeswitch/trunk/src/switch_xml.cpp
==============================================================================
--- freeswitch/trunk/src/switch_xml.cpp (original)
+++ freeswitch/trunk/src/switch_xml.cpp Wed Nov 14 16:01:15 2007
@@ -69,7 +69,7 @@
#define SWITCH_XML_ERRL 128 // maximum error string length
#include "SimpleGlob.h"
-static int preprocess(const char *file, int write_fd, int rlevel);
+static int preprocess(const char *cwd, const char *file, int write_fd, int rlevel);
typedef struct switch_xml_root *switch_xml_root_t;
struct switch_xml_root { // additional data for the root tag
@@ -938,14 +938,15 @@
}
-static int preprocess_glob(const char *pattern, int write_fd, int rlevel)
+static int preprocess_glob(const char *cwd, const char *pattern, int write_fd, int rlevel)
{
char *argv[1] = {0};
int argc = 1;
char *full_path = NULL;
+ char *dir_path = NULL, *e = NULL;
if (!switch_is_file_path(pattern)) {
- full_path = switch_mprintf("%s%s%s", SWITCH_GLOBAL_dirs.conf_dir, SWITCH_PATH_SEPARATOR, pattern);
+ full_path = switch_mprintf("%s%s%s", cwd, SWITCH_PATH_SEPARATOR, pattern);
pattern = full_path;
}
@@ -961,14 +962,19 @@
}
for (int n = 0; n < glob.FileCount(); ++n) {
- if (preprocess(glob.File(n), write_fd, rlevel) < 0) {
+ dir_path = strdup(glob.File(n));
+ assert(dir_path);
+ if ((e = strrchr(dir_path, *SWITCH_PATH_SEPARATOR))) {
+ *e = '\0';
+ }
+ if (preprocess(dir_path, glob.File(n), write_fd, rlevel) < 0) {
const char *reason = strerror(errno);
if (rlevel > 100) {
reason = "Maximum recursion limit reached";
}
fprintf(stderr, "Error including %s (%s)\n", argv[0], reason);
}
-
+ free(dir_path);
}
end:
@@ -978,7 +984,7 @@
return write_fd;
}
-static int preprocess(const char *file, int write_fd, int rlevel)
+static int preprocess(const char *cwd, const char *file, int write_fd, int rlevel)
{
int read_fd = -1;
switch_size_t cur = 0, ml = 0;
@@ -1078,7 +1084,7 @@
}
} else if (!strcasecmp(tcmd, "include")) {
- preprocess_glob(targ, write_fd, rlevel + 1);
+ preprocess_glob(cwd, targ, write_fd, rlevel + 1);
}
continue;
@@ -1134,7 +1140,7 @@
}
} else if (!strcasecmp(cmd, "include")) {
- preprocess_glob(arg, write_fd, rlevel + 1);
+ preprocess_glob(cwd, arg, write_fd, rlevel + 1);
}
}
@@ -1192,7 +1198,7 @@
goto done;
}
- if (preprocess(file, write_fd, 0) > -1) {
+ if (preprocess(SWITCH_GLOBAL_dirs.conf_dir, file, write_fd, 0) > -1) {
close(write_fd);
write_fd = -1;
if ((fd = open(new_file, O_RDONLY, 0)) > -1) {
1
0
Author: mikej
Date: Wed Nov 14 15:42:16 2007
New Revision: 6261
Modified:
freeswitch/trunk/w32/Library/FreeSwitchCore.vcproj
Log:
fix to changing file names
Modified: freeswitch/trunk/w32/Library/FreeSwitchCore.vcproj
==============================================================================
--- freeswitch/trunk/w32/Library/FreeSwitchCore.vcproj (original)
+++ freeswitch/trunk/w32/Library/FreeSwitchCore.vcproj Wed Nov 14 15:42:16 2007
@@ -435,8 +435,18 @@
>
</File>
<File
- RelativePath="..\..\src\switch_xml.c"
+ RelativePath="..\..\src\switch_xml.cpp"
>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderThrough=""
+ PrecompiledHeaderFile=""
+ />
+ </FileConfiguration>
</File>
</Filter>
<Filter
@@ -481,11 +491,11 @@
>
</File>
<File
- RelativePath="..\..\src\include\switch_core.h"
+ RelativePath="..\..\src\include\private\switch_core.h"
>
</File>
<File
- RelativePath="..\..\src\include\private\switch_core.h"
+ RelativePath="..\..\src\include\switch_core.h"
>
</File>
<File
1
0
Author: brian
Date: Wed Nov 14 15:37:01 2007
New Revision: 6260
Added:
freeswitch/trunk/conf/lang/
freeswitch/trunk/conf/lang/de/
freeswitch/trunk/conf/lang/en/
freeswitch/trunk/conf/lang/fr/
Log:
lang
1
0
Author: anthm
Date: Wed Nov 14 15:29:19 2007
New Revision: 6259
Modified:
freeswitch/trunk/conf/freeswitch.xml
freeswitch/trunk/conf/sofia.conf.xml
freeswitch/trunk/conf/vars.xml
Log:
make preprocessor also be a tag for everyone who keeps begging for it
Modified: freeswitch/trunk/conf/freeswitch.xml
==============================================================================
--- freeswitch/trunk/conf/freeswitch.xml (original)
+++ freeswitch/trunk/conf/freeswitch.xml Wed Nov 14 15:29:19 2007
@@ -9,63 +9,66 @@
(note the double $$ which denotes preprocessor variables)
#comment ==> A general comment such as this
- The preprocessor will compile the full xml document to ${prefix}/log/freeswitch.registry
+ The preprocessor will compile the full xml document to ${prefix}/log/freeswitch.xml.fsxml
Don't modify it while freeswitch is running cos it is mem mapped in most cases =D
+
+ The same can be achieved with the <X-PRE-PROCESS> tag where the attrs 'cmd' and 'data' are
+ parsed in the same way.
-->
<!--#comment
vars.xml contains all the #set directives for the preprocessor.
-->
- <!--#include "vars.xml"-->
+ <X-PRE-PROCESS cmd="include" data="vars.xml"/>
<section name="configuration" description="Various Configuration">
- <!--#include "switch.conf.xml"-->
- <!--#include "modules.conf.xml"-->
+ <X-PRE-PROCESS cmd="include" data="switch.conf.xml"/>
+ <X-PRE-PROCESS cmd="include" data="modules.conf.xml"/>
<!-- Order doesn't matter, but for clarity these are in same order as modules.conf.xml.
If they aren't loaded by modules.conf.xml, then they are ignored.
-->
<!-- Loggers -->
- <!--#include "console.conf.xml"-->
- <!--#include "syslog.conf.xml"-->
+ <X-PRE-PROCESS cmd="include" data="console.conf.xml"/>
+ <X-PRE-PROCESS cmd="include" data="syslog.conf.xml"/>
<!-- Multi-Faceted -->
- <!--#include "enum.conf.xml"-->
+ <X-PRE-PROCESS cmd="include" data="enum.conf.xml"/>
<!-- XML Interfaces -->
- <!--#include "xml_rpc.conf.xml"-->
- <!--#include "xml_cdr.conf.xml"-->
- <!--#include "xml_curl.conf.xml"-->
+ <X-PRE-PROCESS cmd="include" data="xml_rpc.conf.xml"/>
+ <X-PRE-PROCESS cmd="include" data="xml_cdr.conf.xml"/>
+ <X-PRE-PROCESS cmd="include" data="xml_curl.conf.xml"/>
<!-- none for mod_xml_cdr -->
<!-- Event Handlers -->
- <!--#include "cdr.conf.xml"-->
- <!--#include "event_multicast.conf.xml"-->
- <!--#include "event_socket.conf.xml"-->
- <!--#include "xmpp_event.conf.xml"-->
- <!--#include "zeroconf.conf.xml"-->
+ <X-PRE-PROCESS cmd="include" data="cdr.conf.xml"/>
+ <X-PRE-PROCESS cmd="include" data="event_multicast.conf.xml"/>
+ <X-PRE-PROCESS cmd="include" data="event_socket.conf.xml"/>
+ <X-PRE-PROCESS cmd="include" data="xmpp_event.conf.xml"/>
+ <X-PRE-PROCESS cmd="include" data="zeroconf.conf.xml"/>
<!-- Directory Interfaces -->
<!-- none for mod_ldap; dialplan_directory.conf.xml has ldap connection info -->
<!-- Endpoints -->
- <!--#include "dingaling.conf.xml"-->
- <!--#include "iax.conf.xml"-->
- <!--#include "portaudio.conf.xml"-->
- <!--#include "alsa.conf.xml"-->
- <!--#include "sofia.conf.xml"-->
- <!--#include "wanpipe.conf.xml"-->
- <!--#include "woomera.conf.xml"-->
+ <X-PRE-PROCESS cmd="include" data="dingaling.conf.xml"/>
+ <X-PRE-PROCESS cmd="include" data="iax.conf.xml"/>
+ <X-PRE-PROCESS cmd="include" data="portaudio.conf.xml"/>
+ <X-PRE-PROCESS cmd="include" data="alsa.conf.xml"/>
+ <X-PRE-PROCESS cmd="include" data="sofia.conf.xml"/>
+ <X-PRE-PROCESS cmd="include" data="wanpipe.conf.xml"/>
+ <X-PRE-PROCESS cmd="include" data="woomera.conf.xml"/>
<!-- Applications -->
<!-- none for mod_bridgecall, mod_commands, mod_echo, mod_park, mod_playback -->
- <!--#include "conference.conf.xml"-->
+ <X-PRE-PROCESS cmd="include" data="conference.conf.xml"/>
<!-- ivr.conf is used by mod_dptools -->
- <!--#include "ivr.conf.xml"-->
- <!--#include "voicemail.conf.xml"-->
- <!--#include "limit.conf.xml"-->
+ <X-PRE-PROCESS cmd="include" data="ivr.conf.xml"/>
+ <X-PRE-PROCESS cmd="include" data="voicemail.conf.xml"/>
+ <X-PRE-PROCESS cmd="include" data="limit.conf.xml"/>
<!-- Dialplan Interfaces -->
- <!--#include "dialplan_directory.conf.xml"-->
+ <X-PRE-PROCESS cmd="include" data="dialplan_directory.conf.xml"/>
<!-- mod_dialplan_xml is configured in the separate "dialplan" section. -->
<!-- Codec Interfaces -->
@@ -76,41 +79,41 @@
<!-- no configuration needed -->
<!-- Languages -->
- <!--#include "spidermonkey.conf.xml"-->
+ <X-PRE-PROCESS cmd="include" data="spidermonkey.conf.xml"/>
<!-- none for mod_perl -->
- <!--#include "java.conf.xml"-->
+ <X-PRE-PROCESS cmd="include" data="java.conf.xml"/>
<!-- ASR /TTS -->
<!-- none for mod_cepstral -->
- <!--#include "rss.conf.xml"-->
- <!--#include "mod_openmrcp.conf.xml"-->
+ <X-PRE-PROCESS cmd="include" data="rss.conf.xml"/>
+ <X-PRE-PROCESS cmd="include" data="mod_openmrcp.conf.xml"/>
<!-- Say -->
<!-- none for mod_say_en -->
- <!--#include "mod_cdr.conf.xml"-->
- <!--#include "mod_local_stream.conf.xml"-->
+ <X-PRE-PROCESS cmd="include" data="mod_cdr.conf.xml"/>
+ <X-PRE-PROCESS cmd="include" data="mod_local_stream.conf.xml"/>
</section>
<section name="dialplan" description="Regex/XML Dialplan">
- <!--#include "dialplan/*.xml"-->
+ <X-PRE-PROCESS cmd="include" data="dialplan/*.xml"/>
</section>
<!-- mod_dingaling is reliant on the vcard data in the "directory" section. -->
<!-- mod_sofia is reliant on the user data for authorization -->
<section name="directory" description="User Directory">
- <!--#include "directory/*.xml"-->
+ <X-PRE-PROCESS cmd="include" data="directory/*.xml"/>
</section>
<!-- phrases section (under development still) -->
<section name="phrases" description="Speech Phrase Management">
<macros>
<language name="en" sound-path="/snds" tts-engine="cepstral" tts-voice="david">
- <!--#include "lang_en.xml"-->
+ <X-PRE-PROCESS cmd="include" data="lang_en.xml"/>
<!--voicemail_en_tts is purely implemented with tts, we need a files based implementation too -->
- <!--#include "voicemail_en_tts.xml"-->
+ <X-PRE-PROCESS cmd="include" data="voicemail_en_tts.xml"/>
</language>
<language name="fr" sound_path="/var/sounds/lang/fr/jean" tts_engine="cepstral" tts_voice="jean-pierre">
- <!--#include "lang_fr.xml"-->
+ <X-PRE-PROCESS cmd="include" data="lang_fr.xml"/>
</language>
</macros>
</section>
Modified: freeswitch/trunk/conf/sofia.conf.xml
==============================================================================
--- freeswitch/trunk/conf/sofia.conf.xml (original)
+++ freeswitch/trunk/conf/sofia.conf.xml Wed Nov 14 15:29:19 2007
@@ -1,5 +1,5 @@
<configuration name="sofia.conf" description="sofia Endpoint">
<profiles>
- <!--#include "sip_profiles/*.xml" -->
+ <X-PRE-PROCESS cmd="include" data="sip_profiles/*.xml"/>
</profiles>
</configuration>
Modified: freeswitch/trunk/conf/vars.xml
==============================================================================
--- freeswitch/trunk/conf/vars.xml (original)
+++ freeswitch/trunk/conf/vars.xml Wed Nov 14 15:29:19 2007
@@ -1,23 +1,23 @@
<!-- Preprocessor Variables
These are introduced when configuration strings must be consistent across modules.
-->
- <!--#set "domain=$${local_ip_v4}"-->
+ <X-PRE-PROCESS cmd="set" data="domain=$${local_ip_v4}"/>
<!-- sip_profile
Must be a domain name if you are being a registry server; otherwise
can be any string.
used by: sofia.conf.xml enum.conf.xml default_context.xml directory.xml
-->
- <!--#set "sip_profile=$${domain}"-->
- <!--#set "nat_sip_profile=nat_$${domain}"-->
+ <X-PRE-PROCESS cmd="set" data="sip_profile=$${domain}"/>
+ <X-PRE-PROCESS cmd="set" data="nat_sip_profile=nat_$${domain}"/>
<!-- xmpp_client_profile and xmpp_server_profile
xmpp_client_profile can be any string.
xmpp_server_profile is appended to "dingaling_" to form the database name
containing the "subscriptions" table.
used by: dingaling.conf.xml enum.conf.xml
-->
- <!--#set "global_codec_prefs=PCMU@20i"-->
- <!--#set "xmpp_client_profile=xmppc"-->
- <!--#set "xmpp_server_profile=xmpps"-->
+ <X-PRE-PROCESS cmd="set" data="global_codec_prefs=PCMU@20i"/>
+ <X-PRE-PROCESS cmd="set" data="xmpp_client_profile=xmppc"/>
+ <X-PRE-PROCESS cmd="set" data="xmpp_server_profile=xmpps"/>
<!-- bind_server_ip
Can be an ip address, a dns name, or "auto".
This determines an ip address available on this host to bind.
@@ -25,21 +25,21 @@
use different addresses where this variable appears.
Used by: sofia.conf.xml dingaling.conf.xml
-->
- <!--#set "bind_server_ip=auto"-->
+ <X-PRE-PROCESS cmd="set" data="bind_server_ip=auto"/>
<!-- external_rtp_ip
Used as the public IP address for SDP.
Can be an ip address or a string like "stun:stun.server.com"
If unspecified, the bind_server_ip value is used.
Used by: sofia.conf.xml dingaling.conf.xml
-->
- <!--#set "external_rtp_ip=stun:stun.fwdnet.net"-->
+ <X-PRE-PROCESS cmd="set" data="external_rtp_ip=stun:stun.fwdnet.net"/>
<!-- external_sip_ip
Used as the public IP address for SDP.
Can be an ip address or a string like "stun:stun.server.com"
If unspecified, the bind_server_ip value is used.
Used by: sofia.conf.xml dingaling.conf.xml
-->
- <!--#set "external_sip_ip=stun:stun.fwdnet.net"-->
+ <X-PRE-PROCESS cmd="set" data="external_sip_ip=stun:stun.fwdnet.net"/>
<!-- server_name
A public ip address or DNS name that is used when advertising conference
presence or registering sip.
@@ -49,6 +49,6 @@
The caller ID telephone number we should use when calling out.
Used by: conference.conf.xml
-->
- <!--#set "outbound_caller_name=FreeSWITCH"-->
- <!--#set "outbound_caller_id=8777423583"-->
+ <X-PRE-PROCESS cmd="set" data="outbound_caller_name=FreeSWITCH"/>
+ <X-PRE-PROCESS cmd="set" data="outbound_caller_id=8777423583"/>
1
0
Author: anthm
Date: Wed Nov 14 15:18:46 2007
New Revision: 6258
Modified:
freeswitch/trunk/src/switch_xml.cpp
Log:
add <X-PRE-PROCESS> tag
Modified: freeswitch/trunk/src/switch_xml.cpp
==============================================================================
--- freeswitch/trunk/src/switch_xml.cpp (original)
+++ freeswitch/trunk/src/switch_xml.cpp Wed Nov 14 15:18:46 2007
@@ -983,6 +983,7 @@
int read_fd = -1;
switch_size_t cur = 0, ml = 0;
char *q, *cmd, buf[2048], ebuf[8192];
+ const char *tcmd, *targ;
if ((read_fd = open(file, O_RDONLY, 0)) < 0) {
return read_fd;
@@ -1011,6 +1012,78 @@
}
}
+ if ((tcmd = switch_stristr(bp, "<X-pre-process"))) {
+ if ((e = strstr(tcmd, "/>"))) {
+ *e += 2;
+ *e = '\0';
+ if(write(write_fd, e, (unsigned) strlen(e)) != (int) strlen(e)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Short write!\n");
+ }
+ }
+
+ if (!(tcmd = switch_stristr(tcmd, "cmd"))) {
+ continue;
+ }
+
+ if (!(tcmd = switch_stristr(tcmd, "="))) {
+ continue;
+ }
+
+ if (!(tcmd = switch_stristr(tcmd, "\""))) {
+ continue;
+ }
+
+ tcmd++;
+
+
+ if ((e = strchr(tcmd, '"'))) {
+ *e++ = '\0';
+ }
+
+ if (!(targ = switch_stristr(e, "data"))) {
+ continue;
+ }
+
+ if (!(targ = switch_stristr(targ, "="))) {
+ continue;
+ }
+
+ if (!(targ = switch_stristr(targ, "\""))) {
+ continue;
+ }
+
+ targ++;
+
+ if ((e = strchr(targ, '"'))) {
+ *e++ = '\0';
+ }
+
+ if (!strcasecmp(tcmd, "set")) {
+ char *name = (char *)targ;
+ char *val = strchr(name, '=');
+
+ if (val) {
+ char *ve = val++;
+ while (*val && *val == ' ') {
+ val++;
+ }
+ *ve-- = '\0';
+ while (*ve && *ve == ' ') {
+ *ve-- = '\0';
+ }
+ }
+
+ if (name && val) {
+ switch_core_set_variable(name, val);
+ }
+
+ } else if (!strcasecmp(tcmd, "include")) {
+ preprocess_glob(targ, write_fd, rlevel + 1);
+ }
+
+ continue;
+ }
+
if ((cmd = strstr(bp, "<!--#"))) {
if(write(write_fd, bp, (unsigned) (cmd - bp)) != (cmd - bp)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Short write!\n");
1
0
Author: anthm
Date: Wed Nov 14 14:26:44 2007
New Revision: 6257
Added:
freeswitch/trunk/src/include/SimpleGlob.h
Log:
better globbing
Added: freeswitch/trunk/src/include/SimpleGlob.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/include/SimpleGlob.h Wed Nov 14 14:26:44 2007
@@ -0,0 +1,848 @@
+/*! @file SimpleGlob.h
+
+ @version 2.8
+
+ @brief A cross-platform file globbing library providing the ability to
+ expand wildcards in command-line arguments to a list of all matching files.
+ It is designed explicitly to be portable to any platform and has been tested on
+ Windows and Linux. See CSimpleGlobTempl for the class definition.
+
+ @section features FEATURES
+
+ - MIT Licence allows free use in all software (including GPL and commercial)
+ - multi-platform (Windows 95/98/ME/NT/2K/XP, Linux, Unix)
+ - supports most of the standard linux glob() options
+ - recognition of a forward paths as equivalent to a backward slash on Windows.
+ e.g. "c:/path/foo*" is equivalent to "c:\path\foo*".
+ - implemented with only a single C++ header file
+ - char, wchar_t and Windows TCHAR in the same program
+ - complete working examples included
+ - compiles cleanly at warning level 4 (Windows/VC.NET 2003), warning level
+ 3 (Windows/VC6) and -Wall (Linux/gcc)
+
+ @section usage USAGE
+
+ The SimpleGlob class is used by following these steps:
+
+ <ol>
+ <li> Include the SimpleGlob.h header file
+
+ <pre>
+ \#include "SimpleGlob.h"
+ </pre>
+
+ <li> Instantiate a CSimpleGlob object supplying the appropriate flags.
+
+ <pre>
+ @link CSimpleGlobTempl CSimpleGlob @endlink glob(FLAGS);
+ </pre>
+
+ <li> Add all file specifications to the glob class.
+
+ <pre>
+ glob.Add("file*");
+ glob.Add(argc, argv);
+ </pre>
+
+ <li> Process all files with File(), Files() and FileCount()
+
+ <pre>
+ for (int n = 0; n < glob.FileCount(); ++n) {
+ ProcessFile(glob.File(n));
+ }
+ </pre>
+
+ </ol>
+
+ @section licence MIT LICENCE
+
+ The licence text below is the boilerplate "MIT Licence" used from:
+ http://www.opensource.org/licenses/mit-license.php
+
+ Copyright (c) 2006-2007, Brodie Thiesfield
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is furnished
+ to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef INCLUDED_SimpleGlob
+#define INCLUDED_SimpleGlob
+
+/*! @brief The operation of SimpleGlob is fine-tuned via the use of a combination
+ of the following flags.
+
+ The flags may be passed at initialization of the class and used for every
+ filespec added, or alternatively they may optionally be specified in the
+ call to Add() and be different for each filespec.
+
+ @param SG_GLOB_ERR
+ Return upon read error (e.g. directory does not have read permission)
+
+ @param SG_GLOB_MARK
+ Append a slash (backslash in Windows) to every path which corresponds
+ to a directory
+
+ @param SG_GLOB_NOSORT
+ By default, files are returned in sorted into string order. With this
+ flag, no sorting is done. This is not compatible with SG_GLOB_FULLSORT.
+
+ @param SG_GLOB_FULLSORT
+ By default, files are sorted in groups belonging to each filespec that
+ was added. For example if the filespec "b*" was added before the filespec
+ "a*" then the argv array will contain all b* files sorted in order,
+ followed by all a* files sorted in order. If this flag is specified, the
+ entire array will be sorted ignoring the filespec groups.
+
+ @param SG_GLOB_NOCHECK
+ If the pattern doesn't match anything, return the original pattern.
+
+ @param SG_GLOB_TILDE
+ Tilde expansion is carried out (on Unix platforms)
+
+ @param SG_GLOB_ONLYDIR
+ Return only directories which match (not compatible with SG_GLOB_ONLYFILE)
+
+ @param SG_GLOB_ONLYFILE
+ Return only files which match (not compatible with SG_GLOB_ONLYDIR)
+
+ @param SG_GLOB_NODOT
+ Do not return the "." or ".." special directories.
+ */
+enum SG_Flags {
+ SG_GLOB_ERR = 1 << 0,
+ SG_GLOB_MARK = 1 << 1,
+ SG_GLOB_NOSORT = 1 << 2,
+ SG_GLOB_NOCHECK = 1 << 3,
+ SG_GLOB_TILDE = 1 << 4,
+ SG_GLOB_ONLYDIR = 1 << 5,
+ SG_GLOB_ONLYFILE = 1 << 6,
+ SG_GLOB_NODOT = 1 << 7,
+ SG_GLOB_FULLSORT = 1 << 8
+};
+
+/*! @brief Error return codes */
+enum SG_Error {
+ SG_SUCCESS = 0,
+ SG_ERR_NOMATCH = 1,
+ SG_ERR_MEMORY = -1,
+ SG_ERR_FAILURE = -2
+};
+
+// ----------------------------------------------------------------------------
+// Platform dependent implementations
+
+// don't include this in documentation as it isn't relevant
+#ifndef DOXYGEN
+
+// on Windows we want to use MBCS aware string functions and mimic the
+// Unix glob functionality. On Unix we just use glob.
+#ifdef _WIN32
+# include <mbstring.h>
+# define sg_strchr ::_mbschr
+# define sg_strrchr ::_mbsrchr
+# define sg_strlen ::_mbslen
+# if __STDC_WANT_SECURE_LIB__
+# define sg_strcpy_s(a,n,b) ::_mbscpy_s(a,n,b)
+# else
+# define sg_strcpy_s(a,n,b) ::_mbscpy(a,b)
+# endif
+# define sg_strcmp ::_mbscmp
+# define sg_strcasecmp ::_mbsicmp
+# define SOCHAR_T unsigned char
+#else
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <glob.h>
+# include <limits.h>
+# define MAX_PATH PATH_MAX
+# define sg_strchr ::strchr
+# define sg_strrchr ::strrchr
+# define sg_strlen ::strlen
+# define sg_strcpy_s(a,n,b) ::strcpy(a,b)
+# define sg_strcmp ::strcmp
+# define sg_strcasecmp ::strcasecmp
+# define SOCHAR_T char
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+// use assertions to test the input data
+#ifdef _DEBUG
+# ifdef _WIN32
+# include <crtdbg.h>
+# define SG_ASSERT(b) _ASSERTE(b)
+# else
+# include <assert.h>
+# define SG_ASSERT(b) assert(b)
+# endif
+#else
+# define SG_ASSERT(b)
+#endif
+
+/*! @brief String manipulation functions. */
+class SimpleGlobUtil
+{
+public:
+ static const char * strchr(const char *s, char c) {
+ return (char *) sg_strchr((const SOCHAR_T *)s, c);
+ }
+ static const wchar_t * strchr(const wchar_t *s, wchar_t c) {
+ return ::wcschr(s, c);
+ }
+
+ static const char * strrchr(const char *s, char c) {
+ return (char *) sg_strrchr((const SOCHAR_T *)s, c);
+ }
+ static const wchar_t * strrchr(const wchar_t *s, wchar_t c) {
+ return ::wcsrchr(s, c);
+ }
+
+ // Note: char strlen returns number of bytes, not characters
+ static size_t strlen(const char *s) { return ::strlen(s); }
+ static size_t strlen(const wchar_t *s) { return ::wcslen(s); }
+
+ static void strcpy_s(char *dst, size_t n, const char *src) {
+ (void) n;
+ sg_strcpy_s((SOCHAR_T *)dst, n, (const SOCHAR_T *)src);
+ }
+ static void strcpy_s(wchar_t *dst, size_t n, const wchar_t *src) {
+# if __STDC_WANT_SECURE_LIB__
+ ::wcscpy_s(dst, n, src);
+#else
+ (void) n;
+ ::wcscpy(dst, src);
+#endif
+ }
+
+ static int strcmp(const char *s1, const char *s2) {
+ return sg_strcmp((const SOCHAR_T *)s1, (const SOCHAR_T *)s2);
+ }
+ static int strcmp(const wchar_t *s1, const wchar_t *s2) {
+ return ::wcscmp(s1, s2);
+ }
+
+ static int strcasecmp(const char *s1, const char *s2) {
+ return sg_strcasecmp((const SOCHAR_T *)s1, (const SOCHAR_T *)s2);
+ }
+#if _WIN32
+ static int strcasecmp(const wchar_t *s1, const wchar_t *s2) {
+ return ::_wcsicmp(s1, s2);
+ }
+#endif // _WIN32
+};
+
+enum SG_FileType {
+ SG_FILETYPE_INVALID,
+ SG_FILETYPE_FILE,
+ SG_FILETYPE_DIR
+};
+
+#ifdef _WIN32
+
+#ifndef INVALID_FILE_ATTRIBUTES
+# define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
+#endif
+
+#define SG_PATH_CHAR '\\'
+
+/*! @brief Windows glob implementation. */
+template<class SOCHAR>
+struct SimpleGlobBase
+{
+ SimpleGlobBase() : m_hFind(INVALID_HANDLE_VALUE) { }
+
+ int FindFirstFileS(const char * a_pszFileSpec, unsigned int) {
+ m_hFind = FindFirstFileA(a_pszFileSpec, &m_oFindDataA);
+ if (m_hFind != INVALID_HANDLE_VALUE) {
+ return SG_SUCCESS;
+ }
+ DWORD dwErr = GetLastError();
+ if (dwErr == ERROR_FILE_NOT_FOUND) {
+ return SG_ERR_NOMATCH;
+ }
+ return SG_ERR_FAILURE;
+ }
+ int FindFirstFileS(const wchar_t * a_pszFileSpec, unsigned int) {
+ m_hFind = FindFirstFileW(a_pszFileSpec, &m_oFindDataW);
+ if (m_hFind != INVALID_HANDLE_VALUE) {
+ return SG_SUCCESS;
+ }
+ DWORD dwErr = GetLastError();
+ if (dwErr == ERROR_FILE_NOT_FOUND) {
+ return SG_ERR_NOMATCH;
+ }
+ return SG_ERR_FAILURE;
+ }
+
+ bool FindNextFileS(char) {
+ return FindNextFileA(m_hFind, &m_oFindDataA) != FALSE;
+ }
+ bool FindNextFileS(wchar_t) {
+ return FindNextFileW(m_hFind, &m_oFindDataW) != FALSE;
+ }
+
+ void FindDone() {
+ FindClose(m_hFind);
+ }
+
+ const char * GetFileNameS(char) const {
+ return m_oFindDataA.cFileName;
+ }
+ const wchar_t * GetFileNameS(wchar_t) const {
+ return m_oFindDataW.cFileName;
+ }
+
+ bool IsDirS(char) const {
+ return GetFileTypeS(m_oFindDataA.dwFileAttributes) == SG_FILETYPE_DIR;
+ }
+ bool IsDirS(wchar_t) const {
+ return GetFileTypeS(m_oFindDataW.dwFileAttributes) == SG_FILETYPE_DIR;
+ }
+
+ SG_FileType GetFileTypeS(const char * a_pszPath) {
+ return GetFileTypeS(GetFileAttributesA(a_pszPath));
+ }
+ SG_FileType GetFileTypeS(const wchar_t * a_pszPath) {
+ return GetFileTypeS(GetFileAttributesW(a_pszPath));
+ }
+ SG_FileType GetFileTypeS(DWORD a_dwAttribs) const {
+ if (a_dwAttribs == INVALID_FILE_ATTRIBUTES) {
+ return SG_FILETYPE_INVALID;
+ }
+ if (a_dwAttribs & FILE_ATTRIBUTE_DIRECTORY) {
+ return SG_FILETYPE_DIR;
+ }
+ return SG_FILETYPE_FILE;
+ }
+
+private:
+ HANDLE m_hFind;
+ WIN32_FIND_DATAA m_oFindDataA;
+ WIN32_FIND_DATAW m_oFindDataW;
+};
+
+#else // !_WIN32
+
+#define SG_PATH_CHAR '/'
+
+/*! @brief Unix glob implementation. */
+template<class SOCHAR>
+struct SimpleGlobBase
+{
+ SimpleGlobBase() {
+ memset(&m_glob, 0, sizeof(m_glob));
+ m_uiCurr = (size_t)-1;
+ }
+
+ ~SimpleGlobBase() {
+ globfree(&m_glob);
+ }
+
+ void FilePrep() {
+ m_bIsDir = false;
+ size_t len = strlen(m_glob.gl_pathv[m_uiCurr]);
+ if (m_glob.gl_pathv[m_uiCurr][len-1] == '/') {
+ m_bIsDir = true;
+ m_glob.gl_pathv[m_uiCurr][len-1] = 0;
+ }
+ }
+
+ int FindFirstFileS(const char * a_pszFileSpec, unsigned int a_uiFlags) {
+ int nFlags = GLOB_MARK | GLOB_NOSORT;
+ if (a_uiFlags & SG_GLOB_ERR) nFlags |= GLOB_ERR;
+ if (a_uiFlags & SG_GLOB_TILDE) nFlags |= GLOB_TILDE;
+ int rc = glob(a_pszFileSpec, nFlags, NULL, &m_glob);
+ if (rc == GLOB_NOSPACE) return SG_ERR_MEMORY;
+ if (rc == GLOB_ABORTED) return SG_ERR_FAILURE;
+ if (rc == GLOB_NOMATCH) return SG_ERR_NOMATCH;
+ m_uiCurr = 0;
+ FilePrep();
+ return SG_SUCCESS;
+ }
+
+ bool FindNextFileS(char) {
+ SG_ASSERT(m_uiCurr != (size_t)-1);
+ if (++m_uiCurr >= m_glob.gl_pathc) {
+ return false;
+ }
+ FilePrep();
+ return true;
+ }
+
+ void FindDone() {
+ globfree(&m_glob);
+ memset(&m_glob, 0, sizeof(m_glob));
+ m_uiCurr = (size_t)-1;
+ }
+
+ const char * GetFileNameS(char) const {
+ SG_ASSERT(m_uiCurr != (size_t)-1);
+ return m_glob.gl_pathv[m_uiCurr];
+ }
+
+ bool IsDirS(char) const {
+ SG_ASSERT(m_uiCurr != (size_t)-1);
+ return m_bIsDir;
+ }
+
+ SG_FileType GetFileTypeS(const char * a_pszPath) const {
+ struct stat sb;
+ if (0 != stat(a_pszPath, &sb)) {
+ return SG_FILETYPE_INVALID;
+ }
+ if (S_ISDIR(sb.st_mode)) {
+ return SG_FILETYPE_DIR;
+ }
+ if (S_ISREG(sb.st_mode)) {
+ return SG_FILETYPE_FILE;
+ }
+ return SG_FILETYPE_INVALID;
+ }
+
+private:
+ glob_t m_glob;
+ size_t m_uiCurr;
+ bool m_bIsDir;
+};
+
+#endif // _WIN32
+
+#endif // DOXYGEN
+
+// ---------------------------------------------------------------------------
+// MAIN TEMPLATE CLASS
+// ---------------------------------------------------------------------------
+
+/*! @brief Implementation of the SimpleGlob class */
+template<class SOCHAR>
+class CSimpleGlobTempl : private SimpleGlobBase<SOCHAR>
+{
+public:
+ /*! @brief Initialize the class.
+
+ @param a_uiFlags Combination of SG_GLOB flags.
+ @param a_nReservedSlots Number of slots in the argv array that
+ should be reserved. In the returned array these slots
+ argv[0] ... argv[a_nReservedSlots-1] will be left empty for
+ the caller to fill in.
+ */
+ CSimpleGlobTempl(unsigned int a_uiFlags = 0, int a_nReservedSlots = 0);
+
+ /*! @brief Deallocate all memory buffers. */
+ ~CSimpleGlobTempl();
+
+ /*! @brief Initialize (or re-initialize) the class in preparation for
+ adding new filespecs.
+
+ All existing files are cleared. Note that allocated memory is only
+ deallocated at object destruction.
+
+ @param a_uiFlags Combination of SG_GLOB flags.
+ @param a_nReservedSlots Number of slots in the argv array that
+ should be reserved. In the returned array these slots
+ argv[0] ... argv[a_nReservedSlots-1] will be left empty for
+ the caller to fill in.
+ */
+ int Init(unsigned int a_uiFlags = 0, int a_nReservedSlots = 0);
+
+ /*! @brief Add a new filespec to the glob.
+
+ The filesystem will be immediately scanned for all matching files and
+ directories and they will be added to the glob.
+
+ @param a_pszFileSpec Filespec to add to the glob.
+
+ @return SG_SUCCESS Matching files were added to the glob.
+ @return SG_ERR_NOMATCH Nothing matched the pattern. To ignore this error
+ compare the return value to >= SG_SUCCESS.
+ @return SG_ERR_MEMORY Out of memory failure.
+ @return SG_ERR_FAILURE General failure.
+ */
+ int Add(const SOCHAR *a_pszFileSpec);
+
+ /*! @brief Add an array of filespec to the glob.
+
+ The filesystem will be immediately scanned for all matching files and
+ directories in each filespec and they will be added to the glob.
+
+ @param a_nCount Number of filespec in the array.
+ @param a_rgpszFileSpec Array of filespec to add to the glob.
+
+ @return SG_SUCCESS Matching files were added to the glob.
+ @return SG_ERR_NOMATCH Nothing matched the pattern. To ignore this error
+ compare the return value to >= SG_SUCCESS.
+ @return SG_ERR_MEMORY Out of memory failure.
+ @return SG_ERR_FAILURE General failure.
+ */
+ int Add(int a_nCount, const SOCHAR * const * a_rgpszFileSpec);
+
+ /*! @brief Return the number of files in the argv array.
+ */
+ inline int FileCount() const { return m_nArgsLen; }
+
+ /*! @brief Return the full argv array. */
+ inline SOCHAR ** Files() {
+ SetArgvArrayType(POINTERS);
+ return m_rgpArgs;
+ }
+
+ /*! @brief Return the a single file. */
+ inline SOCHAR * File(int n) {
+ SG_ASSERT(n >= 0 && n < m_nArgsLen);
+ return Files()[n];
+ }
+
+private:
+ /*! @brief The argv array has it's members stored as either an offset into
+ the string buffer, or as pointers to their string in the buffer. The offsets
+ are used because if the string buffer is dynamically resized, all pointers
+ into that buffer would become invalid.
+ */
+ enum ARG_ARRAY_TYPE { OFFSETS, POINTERS };
+
+ /*! @brief Change the type of data stored in the argv array. */
+ void SetArgvArrayType(ARG_ARRAY_TYPE a_nNewType);
+
+ /*! @brief Add a filename to the array if it passes all requirements. */
+ int AppendName(const SOCHAR *a_pszFileName, bool a_bIsDir);
+
+ /*! @brief Grow the argv array to the required size. */
+ bool GrowArgvArray(int a_nNewLen);
+
+ /*! @brief Grow the string buffer to the required size. */
+ bool GrowStringBuffer(size_t a_uiMinSize);
+
+ /*! @brief Compare two (possible NULL) strings */
+ static int fileSortCompare(const void *a1, const void *a2);
+
+private:
+ unsigned int m_uiFlags;
+ ARG_ARRAY_TYPE m_nArgArrayType; //!< is the argv array storing indexes or pointers
+ SOCHAR ** m_rgpArgs; //!< argv array
+ int m_nReservedSlots; //!< number of client reserved slots in the argv array
+ int m_nArgsSize; //!< allocated size of array
+ int m_nArgsLen; //!< used length
+ SOCHAR * m_pBuffer; //!< argv string buffer
+ size_t m_uiBufferSize; //!< allocated size of buffer
+ size_t m_uiBufferLen; //!< used length of buffer
+ SOCHAR m_szPathPrefix[MAX_PATH]; //!< path prefix of any wildcard filenames
+};
+
+// ---------------------------------------------------------------------------
+// IMPLEMENTATION
+// ---------------------------------------------------------------------------
+
+template<class SOCHAR>
+CSimpleGlobTempl<SOCHAR>::CSimpleGlobTempl(
+ unsigned int a_uiFlags,
+ int a_nReservedSlots
+ )
+{
+ m_rgpArgs = NULL;
+ m_nArgsSize = 0;
+ m_pBuffer = NULL;
+ m_uiBufferSize = 0;
+
+ Init(a_uiFlags, a_nReservedSlots);
+}
+
+template<class SOCHAR>
+CSimpleGlobTempl<SOCHAR>::~CSimpleGlobTempl()
+{
+ if (m_rgpArgs) free(m_rgpArgs);
+ if (m_pBuffer) free(m_pBuffer);
+}
+
+template<class SOCHAR>
+int
+CSimpleGlobTempl<SOCHAR>::Init(
+ unsigned int a_uiFlags,
+ int a_nReservedSlots
+ )
+{
+ m_nArgArrayType = POINTERS;
+ m_uiFlags = a_uiFlags;
+ m_nArgsLen = a_nReservedSlots;
+ m_nReservedSlots = a_nReservedSlots;
+ m_uiBufferLen = 0;
+
+ if (m_nReservedSlots > 0) {
+ if (!GrowArgvArray(m_nReservedSlots)) {
+ return SG_ERR_MEMORY;
+ }
+ for (int n = 0; n < m_nReservedSlots; ++n) {
+ m_rgpArgs[n] = NULL;
+ }
+ }
+
+ return SG_SUCCESS;
+}
+
+template<class SOCHAR>
+int
+CSimpleGlobTempl<SOCHAR>::Add(
+ const SOCHAR *a_pszFileSpec
+ )
+{
+#ifdef _WIN32
+ // Windows FindFirst/FindNext recognizes forward slash as the same as backward slash
+ // and follows the directories. We need to do the same when calculating the prefix
+ // and when we have no wildcards.
+ SOCHAR szFileSpec[MAX_PATH];
+ SimpleGlobUtil::strcpy_s(szFileSpec, MAX_PATH, a_pszFileSpec);
+ const SOCHAR * pszPath = SimpleGlobUtil::strchr(szFileSpec, '/');
+ while (pszPath) {
+ szFileSpec[pszPath - szFileSpec] = SG_PATH_CHAR;
+ pszPath = SimpleGlobUtil::strchr(pszPath + 1, '/');
+ }
+ a_pszFileSpec = szFileSpec;
+#endif
+
+ // if this doesn't contain wildcards then we can just add it directly
+ m_szPathPrefix[0] = 0;
+ if (!SimpleGlobUtil::strchr(a_pszFileSpec, '*') &&
+ !SimpleGlobUtil::strchr(a_pszFileSpec, '?'))
+ {
+ SG_FileType nType = GetFileTypeS(a_pszFileSpec);
+ if (nType == SG_FILETYPE_INVALID) {
+ if (m_uiFlags & SG_GLOB_NOCHECK) {
+ return AppendName(a_pszFileSpec, false);
+ }
+ return SG_ERR_NOMATCH;
+ }
+ return AppendName(a_pszFileSpec, nType == SG_FILETYPE_DIR);
+ }
+
+#ifdef _WIN32
+ // Windows doesn't return the directory with the filename, so we need to extract the
+ // path from the search string ourselves and prefix it to the filename we get back.
+ const SOCHAR * pszFilename = SimpleGlobUtil::strrchr(a_pszFileSpec, SG_PATH_CHAR);
+ if (pszFilename) {
+ SimpleGlobUtil::strcpy_s(m_szPathPrefix, MAX_PATH, a_pszFileSpec);
+ m_szPathPrefix[pszFilename - a_pszFileSpec + 1] = 0;
+ }
+#endif
+
+ // search for the first match on the file
+ int rc = FindFirstFileS(a_pszFileSpec, m_uiFlags);
+ if (rc != SG_SUCCESS) {
+ if (rc == SG_ERR_NOMATCH && (m_uiFlags & SG_GLOB_NOCHECK)) {
+ int ok = AppendName(a_pszFileSpec, false);
+ if (ok != SG_SUCCESS) rc = ok;
+ }
+ return rc;
+ }
+
+ // add it and find all subsequent matches
+ int nError, nStartLen = m_nArgsLen;
+ bool bSuccess;
+ do {
+ nError = AppendName(GetFileNameS((SOCHAR)0), IsDirS((SOCHAR)0));
+ bSuccess = FindNextFileS((SOCHAR)0);
+ }
+ while (nError == SG_SUCCESS && bSuccess);
+ SimpleGlobBase<SOCHAR>::FindDone();
+
+ // sort these files if required
+ if (m_nArgsLen > nStartLen && !(m_uiFlags & SG_GLOB_NOSORT)) {
+ if (m_uiFlags & SG_GLOB_FULLSORT) {
+ nStartLen = m_nReservedSlots;
+ }
+ SetArgvArrayType(POINTERS);
+ qsort(
+ m_rgpArgs + nStartLen,
+ m_nArgsLen - nStartLen,
+ sizeof(m_rgpArgs[0]), fileSortCompare);
+ }
+
+ return nError;
+}
+
+template<class SOCHAR>
+int
+CSimpleGlobTempl<SOCHAR>::Add(
+ int a_nCount,
+ const SOCHAR * const * a_rgpszFileSpec
+ )
+{
+ int nResult;
+ for (int n = 0; n < a_nCount; ++n) {
+ nResult = Add(a_rgpszFileSpec[n]);
+ if (nResult != SG_SUCCESS) {
+ return nResult;
+ }
+ }
+ return SG_SUCCESS;
+}
+
+template<class SOCHAR>
+int
+CSimpleGlobTempl<SOCHAR>::AppendName(
+ const SOCHAR * a_pszFileName,
+ bool a_bIsDir
+ )
+{
+ // we need the argv array as offsets in case we resize it
+ SetArgvArrayType(OFFSETS);
+
+ // check for special cases which cause us to ignore this entry
+ if ((m_uiFlags & SG_GLOB_ONLYDIR) && !a_bIsDir) {
+ return SG_SUCCESS;
+ }
+ if ((m_uiFlags & SG_GLOB_ONLYFILE) && a_bIsDir) {
+ return SG_SUCCESS;
+ }
+ if ((m_uiFlags & SG_GLOB_NODOT) && a_bIsDir) {
+ if (a_pszFileName[0] == '.') {
+ if (a_pszFileName[1] == '\0') {
+ return SG_SUCCESS;
+ }
+ if (a_pszFileName[1] == '.' && a_pszFileName[2] == '\0') {
+ return SG_SUCCESS;
+ }
+ }
+ }
+
+ // ensure that we have enough room in the argv array
+ if (!GrowArgvArray(m_nArgsLen + 1)) {
+ return SG_ERR_MEMORY;
+ }
+
+ // ensure that we have enough room in the string buffer
+ size_t uiPrefixLen = SimpleGlobUtil::strlen(m_szPathPrefix);
+ size_t uiLen = uiPrefixLen + SimpleGlobUtil::strlen(a_pszFileName) + 1; // + null character
+ if (a_bIsDir && (m_uiFlags & SG_GLOB_MARK) == SG_GLOB_MARK) {
+ ++uiLen; // need space for the backslash
+ }
+ if (!GrowStringBuffer(m_uiBufferLen + uiLen)) {
+ return SG_ERR_MEMORY;
+ }
+
+ // add this entry
+ m_rgpArgs[m_nArgsLen++] = (SOCHAR*)m_uiBufferLen; // offset from beginning of buffer
+ SimpleGlobUtil::strcpy_s(m_pBuffer + m_uiBufferLen,
+ m_uiBufferSize - m_uiBufferLen, m_szPathPrefix);
+ SimpleGlobUtil::strcpy_s(m_pBuffer + m_uiBufferLen + uiPrefixLen,
+ m_uiBufferSize - m_uiBufferLen - uiPrefixLen, a_pszFileName);
+ m_uiBufferLen += uiLen;
+
+ // add the directory slash if desired
+ if (a_bIsDir && (m_uiFlags & SG_GLOB_MARK) == SG_GLOB_MARK) {
+ const static SOCHAR szDirSlash[] = { SG_PATH_CHAR, 0 };
+ SimpleGlobUtil::strcpy_s(m_pBuffer + m_uiBufferLen - 2,
+ m_uiBufferSize - (m_uiBufferLen - 2), szDirSlash);
+ }
+
+ return SG_SUCCESS;
+}
+
+template<class SOCHAR>
+void
+CSimpleGlobTempl<SOCHAR>::SetArgvArrayType(
+ ARG_ARRAY_TYPE a_nNewType
+ )
+{
+ if (m_nArgArrayType == a_nNewType) return;
+ if (a_nNewType == POINTERS) {
+ SG_ASSERT(m_nArgArrayType == OFFSETS);
+ for (int n = 0; n < m_nArgsLen; ++n) {
+ m_rgpArgs[n] = (m_rgpArgs[n] == (SOCHAR*)-1) ?
+ NULL : m_pBuffer + (size_t) m_rgpArgs[n];
+ }
+ }
+ else {
+ SG_ASSERT(a_nNewType == OFFSETS);
+ SG_ASSERT(m_nArgArrayType == POINTERS);
+ for (int n = 0; n < m_nArgsLen; ++n) {
+ m_rgpArgs[n] = (m_rgpArgs[n] == NULL) ?
+ (SOCHAR*) -1 : (SOCHAR*) (m_rgpArgs[n] - m_pBuffer);
+ }
+ }
+ m_nArgArrayType = a_nNewType;
+}
+
+template<class SOCHAR>
+bool
+CSimpleGlobTempl<SOCHAR>::GrowArgvArray(
+ int a_nNewLen
+ )
+{
+ if (a_nNewLen >= m_nArgsSize) {
+ static const int SG_ARGV_INITIAL_SIZE = 32;
+ int nNewSize = (m_nArgsSize > 0) ? m_nArgsSize * 2 : SG_ARGV_INITIAL_SIZE;
+ while (a_nNewLen >= nNewSize) {
+ nNewSize *= 2;
+ }
+ void * pNewBuffer = realloc(m_rgpArgs, nNewSize * sizeof(SOCHAR*));
+ if (!pNewBuffer) return false;
+ m_nArgsSize = nNewSize;
+ m_rgpArgs = (SOCHAR**) pNewBuffer;
+ }
+ return true;
+}
+
+template<class SOCHAR>
+bool
+CSimpleGlobTempl<SOCHAR>::GrowStringBuffer(
+ size_t a_uiMinSize
+ )
+{
+ if (a_uiMinSize >= m_uiBufferSize) {
+ static const int SG_BUFFER_INITIAL_SIZE = 1024;
+ size_t uiNewSize = (m_uiBufferSize > 0) ? m_uiBufferSize * 2 : SG_BUFFER_INITIAL_SIZE;
+ while (a_uiMinSize >= uiNewSize) {
+ uiNewSize *= 2;
+ }
+ void * pNewBuffer = realloc(m_pBuffer, uiNewSize * sizeof(SOCHAR));
+ if (!pNewBuffer) return false;
+ m_uiBufferSize = uiNewSize;
+ m_pBuffer = (SOCHAR*) pNewBuffer;
+ }
+ return true;
+}
+
+template<class SOCHAR>
+int
+CSimpleGlobTempl<SOCHAR>::fileSortCompare(
+ const void *a1,
+ const void *a2
+ )
+{
+ const SOCHAR * s1 = *(const SOCHAR **)a1;
+ const SOCHAR * s2 = *(const SOCHAR **)a2;
+ if (s1 && s2) {
+ return SimpleGlobUtil::strcasecmp(s1, s2);
+ }
+ // NULL sorts first
+ return s1 == s2 ? 0 : (s1 ? 1 : -1);
+}
+
+// ---------------------------------------------------------------------------
+// TYPE DEFINITIONS
+// ---------------------------------------------------------------------------
+
+typedef CSimpleGlobTempl<char> CSimpleGlobA; /*!< @brief ASCII/MBCS version of CSimpleGlob */
+typedef CSimpleGlobTempl<wchar_t> CSimpleGlobW; /*!< @brief wchar_t version of CSimpleGlob */
+#if defined(_UNICODE)
+# define CSimpleGlob CSimpleGlobW /*!< @brief TCHAR version dependent on if _UNICODE is defined */
+#else
+# define CSimpleGlob CSimpleGlobA /*!< @brief TCHAR version dependent on if _UNICODE is defined */
+#endif
+
+#endif // INCLUDED_SimpleGlob
1
0
Author: anthm
Date: Wed Nov 14 14:25:28 2007
New Revision: 6256
Added:
freeswitch/trunk/src/switch_xml.cpp
- copied, changed from r6254, /freeswitch/trunk/src/switch_xml.c
Removed:
freeswitch/trunk/src/switch_xml.c
Modified:
freeswitch/trunk/Makefile.am
freeswitch/trunk/src/switch_regex.c
Log:
better globbing
Modified: freeswitch/trunk/Makefile.am
==============================================================================
--- freeswitch/trunk/Makefile.am (original)
+++ freeswitch/trunk/Makefile.am Wed Nov 14 14:25:28 2007
@@ -54,7 +54,7 @@
src/switch_ivr.c \
src/switch_stun.c\
src/switch_log.c\
-src/switch_xml.c\
+src/switch_xml.cpp\
src/switch_config.c\
src/switch_time.c\
libs/stfu/stfu.c\
Modified: freeswitch/trunk/src/switch_regex.c
==============================================================================
--- freeswitch/trunk/src/switch_regex.c (original)
+++ freeswitch/trunk/src/switch_regex.c Wed Nov 14 14:25:28 2007
@@ -206,6 +206,8 @@
}
+
+
/* For Emacs:
* Local Variables:
* mode:c
Copied: freeswitch/trunk/src/switch_xml.cpp (from r6254, /freeswitch/trunk/src/switch_xml.c)
==============================================================================
--- /freeswitch/trunk/src/switch_xml.c (original)
+++ freeswitch/trunk/src/switch_xml.cpp Wed Nov 14 14:25:28 2007
@@ -67,6 +67,7 @@
#define SWITCH_XML_WS "\t\r\n " // whitespace
#define SWITCH_XML_ERRL 128 // maximum error string length
+#include "SimpleGlob.h"
static int preprocess(const char *file, int write_fd, int rlevel);
@@ -106,7 +107,8 @@
struct xml_section_t {
const char *name;
- switch_xml_section_t section;
+ //switch_xml_section_t section;
+ uint32_t section;
};
@@ -123,8 +125,9 @@
{
size_t x;
char buf[1024] = "";
- switch_xml_section_t sections = SWITCH_XML_SECTION_RESULT;
-
+ //switch_xml_section_t sections = SWITCH_XML_SECTION_RESULT;
+ uint32_t sections = SWITCH_XML_SECTION_RESULT;
+
if (str) {
for (x = 0; x < strlen(str); x++) {
buf[x] = (char) tolower((int) str[x]);
@@ -138,7 +141,7 @@
}
}
}
- return sections;
+ return (switch_xml_section_t) sections;
}
SWITCH_DECLARE(switch_status_t) switch_xml_bind_search_function(switch_xml_search_function_t function, switch_xml_section_t sections, void *user_data)
@@ -146,7 +149,7 @@
switch_xml_binding_t *binding = NULL, *ptr = NULL;
assert(function != NULL);
- if (!(binding = switch_core_alloc(XML_MEMORY_POOL, sizeof(*binding)))) {
+ if (!(binding = (switch_xml_binding_t *) switch_core_alloc(XML_MEMORY_POOL, sizeof(*binding)))) {
return SWITCH_STATUS_MEMERR;
}
@@ -353,7 +356,7 @@
if (ent[b++]) { // found a match
if ((c = (long) strlen(ent[b])) - 1 > (e = strchr(s, ';')) - s) {
l = (d = (long) (s - r)) + c + (long) strlen(e); // new length
- r = (r == m) ? strcpy(malloc(l), r) : realloc(r, l);
+ r = (r == m) ? strcpy((char *)malloc(l), r) : (char *)realloc(r, l);
e = strchr((s = r + d), ';'); // fix up pointers
}
@@ -411,8 +414,8 @@
xml->txt = s; // initial character content
else { // allocate our own memory and make a copy
xml->txt = (xml->flags & SWITCH_XML_TXTM) // allocate some space
- ? realloc(xml->txt, (l = strlen(xml->txt)) + len)
- : strcpy(malloc((l = strlen(xml->txt)) + len), xml->txt);
+ ? (char *)realloc(xml->txt, (l = strlen(xml->txt)) + len)
+ : strcpy((char *)malloc((l = strlen(xml->txt)) + len), xml->txt);
strcpy(xml->txt + l, s); // add new char content
if (s != m)
free(s); // free s if it was malloced by switch_xml_decode()
@@ -470,13 +473,13 @@
}
if (!root->pi[0])
- *(root->pi = malloc(sizeof(char **))) = NULL; //first pi
+ *(root->pi = (char ***)malloc(sizeof(char **))) = NULL; //first pi
while (root->pi[i] && strcmp(target, root->pi[i][0]))
i++; // find target
if (!root->pi[i]) { // new target
- root->pi = realloc(root->pi, sizeof(char **) * (i + 2));
- root->pi[i] = malloc(sizeof(char *) * 3);
+ root->pi = (char ***)realloc(root->pi, sizeof(char **) * (i + 2));
+ root->pi[i] = (char **)malloc(sizeof(char *) * 3);
root->pi[i][0] = target;
root->pi[i][1] = (char *) (root->pi[i + 1] = NULL); // terminate pi list
root->pi[i][2] = strdup(""); // empty document position list
@@ -484,8 +487,8 @@
while (root->pi[i][j])
j++; // find end of instruction list for this target
- root->pi[i] = realloc(root->pi[i], sizeof(char *) * (j + 3));
- root->pi[i][j + 2] = realloc(root->pi[i][j + 1], j + 1);
+ root->pi[i] = (char **)realloc(root->pi[i], sizeof(char *) * (j + 3));
+ root->pi[i][j + 2] = (char *)realloc(root->pi[i][j + 1], j + 1);
strcpy(root->pi[i][j + 2] + j - 1, (root->xml.name) ? ">" : "<");
root->pi[i][j + 1] = NULL; // null terminate pi list for this target
root->pi[i][j] = s; // set instruction
@@ -497,8 +500,8 @@
char q, *c, *t, *n = NULL, *v, **ent, **pe;
int i, j;
- pe = memcpy(malloc(sizeof(SWITCH_XML_NIL)), SWITCH_XML_NIL, sizeof(SWITCH_XML_NIL));
-
+ pe = (char **)memcpy(malloc(sizeof(SWITCH_XML_NIL)), SWITCH_XML_NIL, sizeof(SWITCH_XML_NIL));
+
for (s[len] = '\0'; s;) {
while (*s && *s != '<' && *s != '%')
s++; // find next declaration
@@ -517,7 +520,7 @@
}
for (i = 0, ent = (*c == '%') ? pe : root->ent; ent[i]; i++);
- ent = realloc(ent, (i + 3) * sizeof(char *)); // space for next ent
+ ent = (char **)realloc(ent, (i + 3) * sizeof(char *)); // space for next ent
if (*c == '%')
pe = ent;
else
@@ -556,7 +559,7 @@
}
s += strspn(s + 1, SWITCH_XML_WS) + 1; // find next token
- c = (strncmp(s, "CDATA", 5)) ? "*" : " "; // is it cdata?
+ c = (strncmp(s, "CDATA", 5)) ? (char *)"*" : (char *)" "; // is it cdata?
if (!strncmp(s, "NOTATION", 8))
s += strspn(s + 8, SWITCH_XML_WS) + 8;
s = (*s == '(') ? strchr(s, ')') : s + strcspn(s, SWITCH_XML_WS);
@@ -582,15 +585,15 @@
}
if (!root->attr[i]) { // new tag name
- root->attr = (!i) ? malloc(2 * sizeof(char **))
- : realloc(root->attr, (i + 2) * sizeof(char **));
- root->attr[i] = malloc(2 * sizeof(char *));
+ root->attr = (!i) ? (char ***)malloc(2 * sizeof(char **))
+ : (char ***)realloc(root->attr, (i + 2) * sizeof(char **));
+ root->attr[i] = (char **)malloc(2 * sizeof(char *));
root->attr[i][0] = t; // set tag name
root->attr[i][1] = (char *) (root->attr[i + 1] = NULL);
}
for (j = 1; root->attr[i][j]; j += 3); // find end of list
- root->attr[i] = realloc(root->attr[i], (j + 4) * sizeof(char *));
+ root->attr[i] = (char **)realloc(root->attr[i], (j + 4) * sizeof(char *));
root->attr[i][j + 3] = NULL; // null terminate list
root->attr[i][j + 2] = c; // is it cdata?
@@ -625,7 +628,7 @@
if (be == -1)
return NULL; // not UTF-16
- u = malloc(max);
+ u = (char *)malloc(max);
for (sl = 2; sl < *len - 1; sl += 2) {
c = (be) ? (((*s)[sl] & 0xFF) << 8) | ((*s)[sl + 1] & 0xFF) //UTF-16BE
: (((*s)[sl + 1] & 0xFF) << 8) | ((*s)[sl] & 0xFF); //UTF-16LE
@@ -636,7 +639,7 @@
}
while (l + 6 > max)
- u = realloc(u, max += SWITCH_XML_BUFSIZE);
+ u = (char *)realloc(u, max += SWITCH_XML_BUFSIZE);
if (c < 0x80)
u[l++] = (char) c; // US-ASCII subset
else { // multi-byte UTF-8 sequence
@@ -648,7 +651,7 @@
u[l++] = (char) (0x80 | ((c >> (6 * --b)) & 0x3F)); // payload
}
}
- return *s = realloc(u, *len = l);
+ return *s = (char *)realloc(u, *len = l);
}
// frees a tag attribute list
@@ -709,10 +712,10 @@
for (i = 0; (a = root->attr[i]) && strcmp(a[0], d); i++);
for (l = 0; *s && *s != '/' && *s != '>'; l += 2) { // new attrib
- attr = (l) ? realloc(attr, (l + 4) * sizeof(char *))
- : malloc(4 * sizeof(char *)); // allocate space
- attr[l + 3] = (l) ? realloc(attr[l + 1], (l / 2) + 2)
- : malloc(2); // mem for list of maloced vals
+ attr = (l) ? (char **)realloc(attr, (l + 4) * sizeof(char *))
+ : (char **)malloc(4 * sizeof(char *)); // allocate space
+ attr[l + 3] = (l) ? (char *)realloc(attr[l + 1], (l / 2) + 2)
+ : (char *)malloc(2); // mem for list of maloced vals
strcpy(attr[l + 3] + (l / 2), " "); // value is not malloced
attr[l + 2] = NULL; // null terminate list
attr[l + 1] = ""; // temporary attribute value
@@ -829,12 +832,12 @@
switch_size_t l, len = 0;
char *s;
- if (!(s = malloc(SWITCH_XML_BUFSIZE)))
+ if (!(s = (char *)malloc(SWITCH_XML_BUFSIZE)))
return NULL;
do {
len += (l = fread((s + len), 1, SWITCH_XML_BUFSIZE, fp));
if (l == SWITCH_XML_BUFSIZE)
- s = realloc(s, len + SWITCH_XML_BUFSIZE);
+ s = (char *)realloc(s, len + SWITCH_XML_BUFSIZE);
} while (s && l == SWITCH_XML_BUFSIZE);
if (!s)
@@ -867,7 +870,7 @@
} else { // mmap failed, read file into memory
#endif // HAVE_MMAP
l = read(fd, m = malloc(st.st_size), st.st_size);
- root = (switch_xml_root_t) switch_xml_parse_str(m, l);
+ root = (switch_xml_root_t) switch_xml_parse_str((char *)m, l);
root->dynamic = 1; // so we know to free s in switch_xml_free()
#ifdef HAVE_MMAP
}
@@ -935,55 +938,42 @@
}
-/* for apr file and directory handling */
-#include <apr_file_io.h>
-
static int preprocess_glob(const char *pattern, int write_fd, int rlevel)
{
+ char *argv[1] = {0};
+ int argc = 1;
+ char *full_path = NULL;
+
+ if (!switch_is_file_path(pattern)) {
+ full_path = switch_mprintf("%s%s%s", SWITCH_GLOBAL_dirs.conf_dir, SWITCH_PATH_SEPARATOR, pattern);
+ pattern = full_path;
+ }
+
+ argv[0] = (char *)pattern;
- switch_array_header_t *result;
- switch_memory_pool_t *pool;
- char **list;
- int i;
- char *p, *dir_path = NULL;
+ CSimpleGlob glob(SG_GLOB_NODOT|SG_GLOB_NOCHECK);
- switch_core_new_memory_pool(&pool);
- assert(pool != NULL);
-
- if (switch_is_file_path(pattern)) {
- dir_path = switch_core_strdup(pool, pattern);
- if ((p = strrchr(dir_path, *SWITCH_PATH_SEPARATOR))) {
- *p = '\0';
- }
- } else {
- p = switch_core_sprintf(pool, "%s%s%s", SWITCH_GLOBAL_dirs.conf_dir, SWITCH_PATH_SEPARATOR, pattern);
- pattern = p;
- dir_path = switch_core_strdup(pool, pattern);
- if ((p = strrchr(dir_path, *SWITCH_PATH_SEPARATOR))) {
- *p = '\0';
+ if (SG_SUCCESS != glob.Add(argc, argv)) {
+ if (stderr) {
+ fprintf(stderr, "Error including %s\n", argv[0]);
}
+ goto end;
}
- switch_match_glob(pattern, &result, pool);
-
- list = (char **)result->elts;
-
- for (i = 0; i < result->nelts; i++) {
- char *path = list[i];
- if (strcmp(path, ".") && strcmp(path, "..")) {
- p = switch_core_sprintf(pool, "%s%s%s", dir_path, SWITCH_PATH_SEPARATOR, path);
- if (preprocess(p, write_fd, rlevel) < 0) {
- const char *reason = strerror(errno);
- if (rlevel > 100) {
- reason = "Maximum recursion limit reached";
- }
- fprintf(stderr, "Error including %s (%s)\n", p, reason);
+ for (int n = 0; n < glob.FileCount(); ++n) {
+ if (preprocess(glob.File(n), write_fd, rlevel) < 0) {
+ const char *reason = strerror(errno);
+ if (rlevel > 100) {
+ reason = "Maximum recursion limit reached";
}
+ fprintf(stderr, "Error including %s (%s)\n", argv[0], reason);
}
+
}
- switch_core_destroy_memory_pool(&pool);
-
+ end:
+
+ switch_safe_free(full_path);
return write_fd;
}
@@ -1099,7 +1089,7 @@
if ((fd = open(file, O_RDONLY, 0)) > -1) {
fstat(fd, &st);
l = read(fd, m = malloc(st.st_size), st.st_size);
- root = (switch_xml_root_t) switch_xml_parse_str(m, l);
+ root = (switch_xml_root_t) switch_xml_parse_str((char *)m, l);
root->dynamic = 1;
close(fd);
return &root->xml;
@@ -1404,7 +1394,7 @@
while (s != e) {
while (*dlen + 10 > *max)
- *dst = realloc(*dst, *max += SWITCH_XML_BUFSIZE);
+ *dst = (char *)realloc(*dst, *max += SWITCH_XML_BUFSIZE);
switch (*s) {
case '\0':
@@ -1445,7 +1435,7 @@
static char *switch_xml_toxml_r(switch_xml_t xml, char **s, switch_size_t *len, switch_size_t *max, switch_size_t start, char ***attr, uint32_t * count)
{
int i, j;
- char *txt = (xml->parent) ? xml->parent->txt : "";
+ char *txt = (char *)(xml->parent) ? xml->parent->txt : (char *)"";
switch_size_t off = 0;
uint32_t lcount = 0;
@@ -1453,7 +1443,7 @@
*s = switch_xml_ampencode(txt + start, xml->off - start, s, len, max, 0);
while (*len + strlen(xml->name) + 5 + (strlen(XML_INDENT) * (*count)) + 1 > *max) // reallocate s
- *s = realloc(*s, *max += SWITCH_XML_BUFSIZE);
+ *s = (char *)realloc(*s, *max += SWITCH_XML_BUFSIZE);
if (*(*s + (*len) - 1) == '>') {
*len += sprintf(*s + *len, "\n"); // indent
@@ -1467,7 +1457,7 @@
if (switch_xml_attr(xml, xml->attr[i]) != xml->attr[i + 1])
continue;
while (*len + strlen(xml->attr[i]) + 7 + (strlen(XML_INDENT) * (*count)) > *max) // reallocate s
- *s = realloc(*s, *max += SWITCH_XML_BUFSIZE);
+ *s = (char *)realloc(*s, *max += SWITCH_XML_BUFSIZE);
*len += sprintf(*s + *len, " %s=\"", xml->attr[i]);
switch_xml_ampencode(xml->attr[i + 1], 0, s, len, max, 1);
@@ -1479,7 +1469,7 @@
if (!attr[i][j + 1] || switch_xml_attr(xml, attr[i][j]) != attr[i][j + 1])
continue; // skip duplicates and non-values
while (*len + strlen(attr[i][j]) + 8 + (strlen(XML_INDENT) * (*count)) > *max) // reallocate s
- *s = realloc(*s, *max += SWITCH_XML_BUFSIZE);
+ *s = (char *)realloc(*s, *max += SWITCH_XML_BUFSIZE);
*len += sprintf(*s + *len, " %s=\"", attr[i][j]);
switch_xml_ampencode(attr[i][j + 1], 0, s, len, max, 1);
@@ -1497,7 +1487,7 @@
}
while (*len + strlen(xml->name) + 5 + (strlen(XML_INDENT) * (*count)) > *max) // reallocate s
- *s = realloc(*s, *max += SWITCH_XML_BUFSIZE);
+ *s = (char *)realloc(*s, *max += SWITCH_XML_BUFSIZE);
if (xml->child || xml->txt) {
@@ -1525,7 +1515,7 @@
SWITCH_DECLARE(char *) switch_xml_toxml(switch_xml_t xml)
{
char *s;
- s = malloc(SWITCH_XML_BUFSIZE);
+ s = (char *)malloc(SWITCH_XML_BUFSIZE);
return switch_xml_toxml_buf(xml, s, SWITCH_XML_BUFSIZE, 0);
}
@@ -1548,7 +1538,7 @@
if (!xml || !xml->name) {
- if (!(r = realloc(s, len + 1))) {
+ if (!(r = (char *)realloc(s, len + 1))) {
abort();
}
return r;
@@ -1565,7 +1555,7 @@
continue; // not pre-root
}
while (len + strlen(t = root->pi[i][0]) + strlen(n) + 7 > max) {
- if (!(r = realloc(s, max += SWITCH_XML_BUFSIZE))) {
+ if (!(r = (char *)realloc(s, max += SWITCH_XML_BUFSIZE))) {
abort();
}
s = r;
@@ -1586,7 +1576,7 @@
continue; // not post-root
}
while (len + strlen(t = root->pi[i][0]) + strlen(n) + 7 > max) {
- if (!(r = realloc(s, max += SWITCH_XML_BUFSIZE))) {
+ if (!(r = (char *)realloc(s, max += SWITCH_XML_BUFSIZE))) {
abort();
}
s = r;
@@ -1595,7 +1585,7 @@
}
}
- if (!(r = realloc(s, len + 1))) {
+ if (!(r = (char *)realloc(s, len + 1))) {
abort();
}
@@ -1692,7 +1682,7 @@
root->xml.name = (char *) name;
root->cur = &root->xml;
strcpy(root->err, root->xml.txt = "");
- root->ent = memcpy(malloc(sizeof(ent)), ent, sizeof(ent));
+ root->ent = (char **)memcpy(malloc(sizeof(ent)), ent, sizeof(ent));
root->attr = root->pi = (char ***) (root->xml.attr = SWITCH_XML_NIL);
return &root->xml;
}
@@ -1781,14 +1771,14 @@
if (!value)
return xml; // nothing to do
if (xml->attr == SWITCH_XML_NIL) { // first attribute
- xml->attr = malloc(4 * sizeof(char *));
+ xml->attr = (char **)malloc(4 * sizeof(char *));
xml->attr[1] = strdup(""); // empty list of malloced names/vals
} else
- xml->attr = realloc(xml->attr, (l + 4) * sizeof(char *));
+ xml->attr = (char **)realloc(xml->attr, (l + 4) * sizeof(char *));
xml->attr[l] = (char *) name; // set attribute name
xml->attr[l + 2] = NULL; // null terminate attribute list
- xml->attr[l + 3] = realloc(xml->attr[l + 1], (c = (int) strlen(xml->attr[l + 1])) + 2);
+ xml->attr[l + 3] = (char *)realloc(xml->attr[l + 1], (c = (int) strlen(xml->attr[l + 1])) + 2);
strcpy(xml->attr[l + 3] + c, " "); // set name/value as not malloced
if (xml->flags & SWITCH_XML_DUP)
xml->attr[l + 3][c] = SWITCH_XML_NAMEM;
@@ -1809,7 +1799,7 @@
if (xml->attr[c + 1][l / 2] & SWITCH_XML_NAMEM)
free(xml->attr[l]);
memmove(xml->attr + l, xml->attr + l + 2, (c - l + 2) * sizeof(char *));
- xml->attr = realloc(xml->attr, (c + 2) * sizeof(char *));
+ xml->attr = (char **)realloc(xml->attr, (c + 2) * sizeof(char *));
memmove(xml->attr[c + 1] + (l / 2), xml->attr[c + 1] + (l / 2) + 1, (c / 2) - (l / 2)); // fix list of which name/vals are malloced
}
xml->flags &= ~SWITCH_XML_DUP; // clear strdup() flag
1
0