On top of it: The Fireface UCX is the first professional audio interface with Class Compliant mode to work with Apple's iPad, for perfect stereo up to 18 channel recording and playback, and the addition of truly professional I/Os.
8 Outputs . On the rear: 6 balanced TRS outputs. On the front: One additional TRS stereo phones (playback channels 7/8). The high power phones output offers high volumes even with high-impedance headphones.
Sound Quality . Equipped with a new 2011 A/D and D/A high-performance converter design all I/Os operate at up to 192 kHz. The AD/DA conversion supersedes the outstanding technical specifications of the Fireface UC/400 with an impressive 114 dBA dynamic range on both record and playback. The advanced multi-bit converter architecture guarantees excellent S/N and THD specs across a wide analog level range. In the best RME tradition and product philosophy, the UCX converters and preamps have no characteristic "sound" of their own. They neither add nor remove anything, but capture the original signal just as it is.
Low Latency Converters . All analog I/Os use a low latency converter design with impressive 14 samples for the ADC, and 7 samples for the DAC, independent of the used sample rate. These values are about a quarter of the Fireface UC/400 (43/28), and even outperform much more expensive devices. A technical breakthrough that reduces the overall latency of timing critical applications, in live situations, and in computer-based recording studios. The converter latency is so low (0.4 ms at 48 kHz) that it can be ignored, turning analog digital monitoring into real analog-style monitoring!
Professional Level Support . A great converter needs to support the common studio levels for the perfect adaptation to other analog equipment without loosing headroom. Like all other RME devices the UCX supports the common professional studio levels: -10 dBV, +4 dBu, Lo / HiGain. The software-controlled reference levels, realized discretely in the analog domain, ensure highest dynamic range and fidelity.
Quality over quantity . The UCX provides two high-end mic and instrument preamps - built right into the front.
Thanks to the multi-functional rotary encoder and the optional Advanced Remote Control the UCX is not only a perfect desktop level controller for the main monitors and phones. The integrated TotalMix FX high-end mixer provides an impressive set of monitoring control features for modern Mix-In-the-Box studios or live mixing sessions. Among them Dim, source selection, monitor switching, integrated Talkback, a flexible Cue setup, Mute and Mute FX, Mono, Speaker B switching and much more.
Contrary to 3rd party external monitoring controllers, the built-in UCX solution preserves the original sound, as its hardware outputs stay directly connected to the studio monitors, avoiding another device with a possible signal alteration in the signal path.
The flexibility of RME's DSP-driven TotalMix FX monitoring tool set is impressive: any physical output can be assigned to the directly knob-controlled monitor outputs (Main out, Speaker B, Phones 1, 2 ...) - any output can be used. The functions Talkback, Listenback, Mono and Dim will work automatically for the assigned outputs in the expected way. Cue mixes can be sent to a predefined output, an external input can be assigned and monitored with a simple click. Convenience for any studio or live situation at its best.
The UCX provides an integrated connector on the back for RME's remote controls.
The optional Advanced Remote Control (ARC) provides one big wheel dial, a button for level storage/recall, and seven freely programmable buttons - six with LED - for nearly all TotalMix FX functions. Just assign all frequently used TotalMix functions to these buttons.
The remote comes with a flexible, 5 m (16 ft.) long cable.
RME is the only manufacturer that doesn't use a third party USB or FireWire audio technology, but its own, self-developed Hammerfall Audio Core with an outstanding performance and uncompromised pro audio features. RME integrated the latest and most sophisticated version of RME's bus technology, the Hammerfall-X-Core - combining both, USB 2.0 and FireWire - within one half-rack sized interface.
The Class Compliant mode allows for connecting the UCX to any Apple iPadTM !


Gaming on Campus It shall be the policy of bpcc to forbid gaming of any nature on campus.Return to the upper level to park.You must show a printed (or copy on your day trade to win trade scalper phone) email confirmation of your rental.14:502, all..
What is Anchorage AK like today?Stock up on designer shades for less during this eBay sunglasses sale!BUY NOW Electronic E-Gift Card Big W 250 Discount 5 Gift Cards Electronic Live big for less committed to sears craftsman coupon code 2016 keeping prices low everyday across..
Its ideas includes make-up sets, perfumes with a huge Soap and Glory gift half price.So whether you're after ideas for next time, or just something to show you care, be inspired to find the best present for your wonderful mum.Save, was 19.50, then 17.55, now..
If I were buying a toy for a child with Down syndrome (or any kid for that matter) who was 10 months old 18 months old this would be the onewithout a doubt!
You can buy them on the link I posted above for a great price, or from Babies R Us in their five dollar bins at the front of the store.
2.5 We currently use a third party for payment processing.
And some we have kept going back to time and time again.
Scope.1 We value our users and respect your privacy.We take commercially reasonable physical, electronic and administrative steps to maintain the security of the information collected.If applicable, you may have a right to claim compensation for damages caused by a breach of relevant data protection laws.Because its that good!6.8 If you do not receive a response from us to any emails you send to us within ten (10) business days, please send us another email, as your original email may not have been received.You/your/user(s) means you as a user of our Services.This may include third parties who assist us in identifying which ads to deliver and third parties who deliver the advertisements.Enter your email and we'll send you a password reset link. It may not be as easy to find as simply walking into your local Babies R Us, but I promise you its worth taking the time to find it!If you choose to log in to your account with or through a social networking service, we and that service may share certain information about you and your activities.Any payment transactions will be encrypted.
If you are looking for a Christmas gift, birthday present, or a Im your grandma and just want to spoil you rotten gift for a baby born with Down syndrome (or any child 0-12 months old) its my pleasure to present to you the following.
Date last modified: May 18, 2018.


u.s. PiPE and FoundrY co. MEchanical joint Fittings Bro-007 rEVisEd 4.10 u.s. Pipe's c110 Mechanical Joint Fittings are available in 30" through 48" sizes.
Savoy Piping Inc. specializes in ASTM B622 HASTELLOY C22 Seamless Pipe with years of Experience in Manufacturing ASTM B622 UNS N010276 Pipe. we offer high quality, lower cost but the best service.
We Cangzhou Zhongshun Steel can supply welded steel tubing include erw steel pipes,lsaw steel pipes,ssaw steel pipes.Welded Steel pipes surface treatment:varnish,galvanized,painting,coating.If large diameter steel pipe is what you need then Zhongshun Pipe is the pipe fabricator for you.
Flattening shall not exceed 8% of the pipe outside diameter for pressure duties, or 3% of the pipe outside diameter for v acuum duties. T here shall be no significant thinning when the pipe bend radius is 5 x nominal diameter or greater.
the difference is that its closure is a sphere. The body rotates around the centerline of the valve body to open and close. Cast steel flanged ball valves are mainly used to cutt off,distribute,and change the flow direction of the medium in the pipeline.
pipe special application extension wrenches ... high speed steel drill bits ... Snap-on is a trademark, registered in the United States and other countries, of Snap-on Incorporated. Other marks are marks of their respective holders.
A large part of the alkalis and sulfate entering the burning zone is in practice present in the form of molten sulfates.20 In contrast. they form a range of volatile compounds which themselves evaporate partially and are partly retained in the clinker .


Our hairdressers are trained to the highest standards to offer you on trend hair colouring right here in Fareham in Hampshire.
Have you been looking for a new Fareham based hairdressers to meet your entire colour and styling needs? Then you have come to the right place.
Colour specialists are experienced in all areas of hair colour including fashion & colour correction. We make sure we are bringing bang on trend looks to Fareham for you as well as classic natural options too.
On Trend for colour in Hampshire this summer 2015 is still Ombre or dip died as it's also called (where the ends fade to a lighter colour)… this celebrity favourite is still on trend and Kate Preston were one of the first salon in Fareham to specialise in this trend.
We also have blonding experts to make sure you get the perfect blonde result every time with a return to Ultra Platinum tones predicted for this Summer.
So look no further than Fareham Hairdressers Kate Preston Hair and Beauty salon for all your colour needs. We guarantee we will do everything so you leave looking and feeling fantastic.


We generally stick to the theory "Quality Very first, Prestige Supreme". We've been fully committed to furnishing our shoppers with competitively priced high quality solutions, prompt delivery and expert services for Paper Tubes , paper tubes , Paper Tube Box , We are looking forward to forming successful business relationship with new clients in the near future!
"Our personnel are always in the spirit of ""continuous improvement and excellence"", and with the superior quality products, favorable price and good after-sales services, we try to win every customer's trust for Paper Tubes , paper tubes , Paper Tube Box , We solution have passed through the national skilled certification and been well received in our key industry. Our professional engineering team will often be ready to serve you for consultation and feedback. We've been able to also supply you with no cost samples to meet your needs. Best efforts is going to be produced to offer you the very best service and solutions. For anyone who is considering our business and solutions remember to speak to us by sending us emails or get in touch with us right away. As a way to know our solutions and enterprise. lot more you'll be able to come to our factory to find out it. We will constantly welcome guests from around the globe to our firm. o build enterprise. elations with us. You should truly feel absolutely free to make contact with us for small business and we believe we will share the top trading practical experience with all our merchants.


He also revealed that Greece was poised to extend its territorial waters to 12 miles, through two presidential decrees that were in the final stages of preparation at the foreign ministry.
Summarising his nearly four-year term at the head of the ministry, Kotzias said that Greece was now a country that was heard and taken into account, based on its active and multidimensional foreign policy.
"I leave having completed the great step of the 'FYROM issue' with your support, prime minister. I leave happy," Kotzias said.
Greece was on the verge of embarking on a crucial policy that would see its sovereignty expand for the first time in 70 years, since the Dodecanese islands were added to its territory, Kotzias revealed at the handover ceremony.
Kotzias pointed out that extending the terrotorial waters expanded Greece's area of national sovereignty and that as a coastal state, Greece would be exercising all its legal rights.
Be the first to comment on "'I have resigned but I'm happy,' Kotzias says, welcoming vote in FYROM parliament"


140x60cm. Led square white. Storage: Electric trimmer for women bikini. Gp586. Makeup multifunctional. Free shipping for most european countries. Wholesale wenyi. 300g/bag hard wax beans. If(t==3).
Hr hair removal. Roller wax. Razors. Wholesale pulses. Wholesale brush face. Wholesale abbies hair braiding. 1 x epilator, 1 x clean brush, 1 x bag, 1 x english manual. 4j / cm2. Wholesale diagramming tool. Electric nose trimmer, electric hair removal, hair trimmer, hair shave. Charging time: Wholesale kemei epilatorElectric facial body shaver devices.
Voltage rating: Blade hair. Shaver razor / epilator. Features: Product category: Lady induction touch hair remover. Women's epilator. Mini lady electric eyebrow trimmerRobot xiaomi. Km-6630. Epilator laser ipl. Shaver electric epilator. Body  femme. Km - 3018. Cire epilation chaude. Shaving epilators. Lescolton t009. Pot wax. 100% new.


Shipping: L:5.4375"x W:5.4375"x H:5.75" .25 lbs.
Keller Supply Company is proud to present this brushed finished escutcheons and deck plate faucet part, by Elkay. The LK125A is made from premium materials, this Escutcheons And Deck Plate Faucet Part offers great function and value for your home. This fixture is part of Elkay's decorative ELKAY RESIDENTIAL Collection, so make sure to check out other styles of fixtures to accessorize your room.


text:
package hr.fer.zemris.jcms.parsers;

import hr.fer.zemris.jcms.beans.ext.ISVUFileItemBean;

import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Parseri za isvu datoteku koja čuva popis upisanih studenata po predmetima.
 *
 * @author marcupic
 *
 */
public class ISVUFileParser {

	/**
	 * Parsira predani izvor okteta u kojem svaki redak ima sljedeće elemente odvojene znakom tab:
	 *

	 *
jmbag	kratki naziv lokacije

	 *
?	prazno polje koje ne čuva nikakvu informaciju

	 *
isvuCode	isvu šifra kolegija

	 *
?	prazno polje koje ne čuva nikakvu informaciju

	 *
group	oznaka grupe

	 *
lastName, firstName	prezime i ime studenta razdvojeno zarezom

	 *
courseName	naziv kolegija

	 *
year	godina; ovaj podatak ignoriramo kod parsiranja

	 *

	 * Očekuje se da su podaci u streamu zapisani UTF-8 kodnom stranicom.
	 *
	 * @param is izvor okteta
	 * @return lista isvu zapisa
	 * @throws IOException u slučaju pogreške
	 */
	public static List<ISVUFileItemBean> parseTabbedFormat(InputStream is) throws IOException {
		List<String> lines = TextService.inputStreamToUTF8StringList(is);
		return parseTabbedFormat(lines);
	}

	/**
	 * Parsira predani reader u kojem svaki redak ima sljedeće elemente odvojene znakom tab:
	 *

	 *
jmbag	kratki naziv lokacije

	 *
?	prazno polje koje ne čuva nikakvu informaciju

	 *
isvuCode	isvu šifra kolegija

	 *
?	prazno polje koje ne čuva nikakvu informaciju

	 *
group	oznaka grupe

	 *
lastName, firstName	prezime i ime studenta razdvojeno zarezom

	 *
courseName	naziv kolegija

	 *
year	godina; ovaj podatak ignoriramo kod parsiranja

	 *

	 *
	 * @param is reader
	 * @return lista isvu zapisa
	 * @throws IOException u slučaju pogreške
	 */
	public static List<ISVUFileItemBean> parseTabbedFormat(Reader is) throws IOException {
		List<String> lines = TextService.readerToStringList(is);
		return parseTabbedFormat(lines);
	}

	/**
	 * Parsira predanu listu u kojoj svaki redak ima sljedeće elemente odvojene znakom tab:
	 *

	 *
jmbag	kratki naziv lokacije

	 *
?	prazno polje koje ne čuva nikakvu informaciju

	 *
isvuCode	isvu šifra kolegija

	 *
?	prazno polje koje ne čuva nikakvu informaciju

	 *
group	oznaka grupe

	 *
lastName, firstName	prezime i ime studenta razdvojeno zarezom

	 *
courseName	naziv kolegija

	 *
year	godina; ovaj podatak ignoriramo kod parsiranja

	 *

	 *
	 * Parser prilikom izvođenja koristi cache za sve stringove, tako da osigurava će u konačnici
	 * svaki različiti string biti alociran samo jednom prilikom pohrane u listu.
	 *
	 * @param lines retci
	 * @return listu isvu zapisa
	 * @throws IOException u slučaju pogreške
	 */
	public static List<ISVUFileItemBean> parseTabbedFormat(List<String> lines) throws IOException {
		List<ISVUFileItemBean> resultList = new ArrayList<ISVUFileItemBean>(lines.size());
		Map<String, String> cache = new HashMap<String, String>(5000);
		for(String line : lines) {
			String[] elements = TextService.split(line, '#');
			if(elements.length!=8) {
				System.out.println("Pronađen redak pogrešne duljine: "+line);
				continue;
			}
			ISVUFileItemBean item = new ISVUFileItemBean();
			item.setJmbag(fromCache(cache,elements[0]));
			item.setIsvuCode(fromCache(cache,elements[2]));
			item.setGroup(fromCache(cache,elements[4].toUpperCase()));
			int pos = elements[5].indexOf(',');
			String prezime = pos > -1 ? elements[5].substring(0,pos) : elements[5];
			String ime = pos > -1 ? elements[5].substring(pos+1).trim() : "";
			item.setLastName(fromCache(cache,prezime));
			item.setFirstName(fromCache(cache,ime));
			item.setCourseName(fromCache(cache,elements[6]));
			resultList.add(item);
		}
		return resultList;
	}

	private static String fromCache(Map<String, String> cache, String text) {
		String value = cache.get(text);
		if(value!=null) return value;
		value = new String(text);
		cache.put(value, value);
		return value;
	}
}

redpajama_set_name: RedPajamaGithub


表演内容不限,传统和现代, 经典和简易, 美食和健康, 东方和西方, 实用和艺术. 发挥你的创造力,将"美食"展示出来, 让大家共同来欣赏和分享.
1. 报名方法:每个家庭2人,$25报名费,表演30分钟。Please email to hxcs2011@gmail.com with subject "Cooking show" for registration.
Does your son/daughter have cooking talent? Are you interested in cooking with family member in front of camera? It's time to register. Registration fee: $25 per family (max 2 people per family) per time slot (30 minutes). Please email to hxcs2011@gmail.com with subject "Cooking show" for registration.
Teenagers, moms and dads are all welcome.
Cake, desert, drink, veggie, healthy diet food, rice, bread, dumpling, noodle, pasta, hot dog blanket, salad with various dressings, etc.... Be creative.


text:
BuddeComm Market Reports
Nicaragua's telecoms sector lags behind Central American neighbours
Latin America Telefonica Nicaragua America Movil Millicom Yota BuddeComm Market Reports
Nicaragua is the largest and least densely populated country in Central America. The country's steady GDP growth since 2010 belies the low economic base, given that it has the lowest GDP per capita in the region, with some 60% of the population living below the poverty line.
As a result, much of the economic drive has been the result of international assistance, particularly from the World Bank and other agencies.
The proposed construction of a canal between the Pacific and Caribbean with Chinese funding incorporates deep-water ports, an oil pipeline, railroad, and international airport is an ambitious attempt to deliver greater economic benefits to the country. The project is indicative of China's economic encroachment in the region. However, the project has not started due to the negative environmental impact and questions around its viability.
Nicaragua's telecoms market has mirrored the country's poor economic achievements, with fixed-line teledensity and mobile penetration also being the lowest in Central America. The fixed line broadband market remains nascent, with population penetration below 4%. Most internet users are concentrated in the largest cities, given that rural and marginal areas lack access to the most basic telecom infrastructure. Internet cafés provide public access to internet and email services, but these also tend to be restricted to the larger population centres. To address poor infrastructure, the World Bank has funded a project aimed at improving connectivity via a national fibre broadband network. There are separate schemes to improve broadband in eastern regions and provide links to Caribbean submarine cables.
América Móvil's Claro has a clear lead in all of Nicaragua's telecom sectors, including fixed-line, mobile, broadband, and pay TV. The number of mobile subscribers overtook the number of fixed lines in early 2002, and the mobile sector now accounts for most lines in service.
Telefónica sold its operations in Nicaragua to Millicom in 2019. Millicom's Tigo (previously Telefónica's Movistar) is the only company competing with Claro in the fixed-line and mobile market. In the mobile sector, Tigo holds almost a third of the market, but in the fixed-line sector it has only about 10% market share.
Due to a weak regulatory structure and bureaucratic delays, further liberalisation has been a slow process. The market duopoly has dampened the competitive drive between the two main players, and as a result there has been less effort than in neighbouring countries to improve quality and lower prices. Nevertheless, there are other companies operating in the market, including the Russian state corporation Rostejnologuii, Yota Mobile and IWB Holding. In the mobile market China's Xinwei Nicaragua (Xinwei Intelcom) launched services in early 2016, operating under the CooTel banner.
BuddeComm notes that the Covid-19 pandemic continues to have a significant impact on the telecoms market. On the consumer side, spending on telecoms services and devices is under pressure from the financial effect of large-scale job losses and the consequent restriction on disposable incomes. However, the crucial nature of telecom services, both for general communication as well as a tool for home-working, has offset such pressures. In many markets the net effect has been a reduced (and sometimes negative) subscriber growth, which will continue into 2021.
Overall progress towards 5G has been postponed or curtailed in some countries.
Although it is challenging to predict and interpret the long-term impacts of the crisis as it develops, these have been acknowledged in the industry forecasts contained in this report.
The report also covers the responses of the telecom operators as well as government agencies and regulators as they react to the crisis to ensure that citizens can continue to make optimum use of telecom services. This can be reflected in subsidy schemes and the promotion of tele-health and tele-education, among other solutions.
América Móvil announces plan to spin off towers and other related passive infrastructure in Latin American countries;
Nicaragua on the cards to be joined to the Caribbean Express (CX) submarine cable;
Telcor issues regulation requiring operators to preserve data generated from telecom services;
BT Group sells its Latin American units and assets to CIH Telecommunications Americas;
Tigo develops $50 million plan to modernise its mobile network in Nicaragua;
Tigo launches the Mi Tigo self-management tool for customers;
Millicom selects Harmonic to deploy a cloud-based wireline broadband architecture;
Tigo to provide digital services to 830 Walmart stores in Central America;
World Bank approves $80 million credit for the Nicaragua Hurricanes Eta and Iota Emergency Response Project;
Report update includes the regulator's market data, ITU data for 2019, Telecom Maturity Index charts and analyses, recent market developments.
Get a Full Copy of this Report
Developing Telecoms market report summaries are produced in partnership with BuddeCom, the world's largest continually updated online telecommunications research service.
The above article is a summary of the following BuddeCom report:
Report title: Nicaragua - Telecoms, Mobile and Broadband - Statistics and Analyses
Edition: November 2021
Analyst: Henry Lancaster
Companies mentioned in this report: América Móvil, BellSouth, Claro, Datang Mobile, Movistar, Millicom International Cellular (MIC), Nicacel, Telcor, Telefónica, Tigo, Xinwei Telecom, Yota Nicaragua
Single User PDF Licence Price: US$890
For more information or to purchase a copy of the full report please use the following link: https://www.budde.com.au/Research/Nicaragua-Telecoms-Mobile-and-Broadband-Statistics-and-Analyses/?r=83
Latin American giant Millicom is a takeover target
America Movil, Telxius showcase new subsea cable
Tigo Money and Visa offer digital payment solution for Latin America
Mexico's Altan Redes announces end to bankruptcy
Millicom says Latin American fibre optics plan still on track
Entel Chile to sell fibre optic assets but continue offering services
Four operators bag additional spectrum in Tanzania
America Movil spins off Lat Am tower business to new company
Guatemala 5G: now it's Claro's turn
Telmex faces strike action
Tigo demos 5G to Guatemala City shoppers
Millicom takes 100% stake in Tigo Panama
North Korea's telecom sector shrinks even more following Orascom write-down
Planned True-DTAC merger set to alter Thailand's mobile market dynamics
Afghanistan telecom sector's progress threatened by return of Taliban regime
Azerbaijan experiences tepid growth as infrastructure investment lags
Millicom to inject $700m into Central America
Telefónica taps Mavenir for cloud-native IMS Core in three LatAm markets
Brazil hosts 5G backhaul demo over LEO satellite
Mexico's Movistar suggests network sharing will boost its 5G rollout

redpajama_set_name: RedPajamaCommonCrawl


Full Body* Laser Hair Removal – AED 1999!
Are you ready to attain the desired shape or model-like physique that you always dream of? SKN UK Clinic is the best place where all your beauty modifying dreams can come true. We have expertise and specialization in the most innovative cosmetic surgery procedures, just to help you in improving your magnificence from head to toe. We have invested a lot in the modern and state of art equipment and also are devoted to offer you only the best because the Client gratification is one of our top priorities.
At SKN Cosmetic UK Clinic, we have a team of internationally renowned cosmetic surgeons, trichologist and highly proficient support staff. They have specialized in modern plastic and cosmetic surgeries and also in the skin care procedures. The days are gone when you have to live with what you are born with. Because now, you can transform the way you want and turn your flabby body into a model like figure. If you want to get rid of any physical flaws that are bothering or you want to look beautiful, then visit the SKN Cosmetic UK Clinic to further enhance your attractiveness more than before. Our team has helped thousands of people in augmenting their beauty and boosting up their confidence level and have thousands of success stories and happy clients all around the globe.
At the SKN UK Clinic, we have the most advanced equipment and devices. We have successfully performed thousands of procedures by using the fractionated CO2, intense pulse light, clear light, fractional non-ablative laser resurfacing and many other innovative and high tech automation techniques to make the treatment comfortable and painless.
At the SKN UK Clinic, we have a team of proficient, expert, accomplished and skilled dermatologists, trichologist, surgeons and other staff members. They will only provide you the best results.
Dermatologist at SKN UK Clinic are proficient and have expertise in laser physiology and they are skilled to conclude which laser therapy will work best for you, according to your skin condition. We offer you a range of modern laser treatments to help you in enhancing your body, diminishing or removing your physical flaws and rejuvenating your skin.
If you have done immense research and still looking for a reputed clinic with experienced staff then, feel free to consult us. We offer free consultations and our doctors deal their patients individually..
Our surgeons have performed thousands of procedures and surgeries and have thousands of happy clients around the globe with their success stories.
The Major aim of SKN UK Clinic is to only provide best and treat you with admiration, compassion and will guide you properly after thorough examination of whatever your problem is. Keeping all your details private is part of our patient policy and one of our top priorities.
The decision of undergoing Laser Liposuction from your clinic was the best I could have ever made. I am ecstatic and beyond happy by the results.
I am so happy by the result I got from PRP Therapy. My hair has started to grow again, not only the thickness of my hair has significantly improved, but also the quality.
Thank you Skn Clinic, you gave me which I had always wanted, thick hair and youthful looks, great work.
I am amazed by the results of Skin Whitening Treatment. I highly recommend it for everyone looking for a good Laser Treatment Clinic in Dubai.
Our doctors at SKN UK Clinic are internationally recognized from the reputed institutions. As we have the staff of most talented for liposuction, skin care, laser treatment, breast augmentation, and hair transplant procedures.
You Don't Want to Miss This - We have a Special Offer on Home For You. You are just a step away!


put all files in Disc "D:"
God I so want to play this game again <3<3 Even tho the graphics are old I absolutely love this style.
Last edited by downyo; 31-12-16 at 11:46 AM.
Guys, you just need to do all things step by step as i wrote in first post.YOUR IP=127.0.0.1 - local ip192.168.x.x - pc ip x.x.x.x - hamachi ip ectuse only one ip everywhere or it will not work.
Hello great work good job !! I'm planning to create a server of my own even though i dont have any kind of experience related to it.But my question is with those files you gave us can i edit everything in the server? by everything i mean drop rates to changing drops manually like adding mystic stones to mobsters with %60 drops etc.
I think Tuan already setup a VM server files here we just need an English client to play with.
[Portable] Thục Sơn Tân Truyện - 蜀山新传 - Free servers and guide!!!!
@ichimieszo, please comes back and keep translating that Chinese client you had been doing.
I could translate the client but theres a problem :D I don't know how to translate stuff i don't even know what program to use it Other wise it could be easily done.If anyone would teach me how to translate stuff in client or lead me or at least give me a hint i'd gladly translate it.
Wow. They really did it make a private server of Zu online.
I wonder if the client is compatible with tuan's server files.
I got the client but haven't tried to connect to their servers. My main goal is try to connect to tuan's server files so I can enjoy by myself.
Got myself into that private server but dang this MMORPG really not my taste.
You guys are behind this server? Gonna try it for the old times..
Wait, is this the same person behind from that old zuonline.com server?
Last edited by western; 23-03-17 at 06:46 AM.
anyone here able to help ill appreciate.
My chat server fail to connect.. Any solution? I can run the game just fine.. But not the chat.


Angela Bole is executive director of the Independent Book Publishers Association (IBPA), the largest book publishing association in the U.S. serving small presses and self-published authors. IBPA's mission is to lead and serve the independent publishing community by providing advocacy, education, and tools for success.
Prior to joining IBPA, Angela served two years as deputy executive director of the Book Industry Study Group (BISG), an organization that fosters conversation and consensus across all sectors of the book business. Before that, she served two years as BISG's associate director and two years as its marketing and communications manager.
Angela holds a Masters of Science in Book Publishing from New York University and currently serves on the board of directors for BISG and IDPF, the International Digital Publishing Forum. She lives in Redondo Beach, California where she rides her bike to work as often as possible.


Golf is one of the most popular recreational sports in the US today. It is also a leading cause of injury. Most "weekend" golfers develop injury problems from poor swing mechanics and or poor conditioning. Professional golfers and those who play very often can run into problems from overuse. Here are some helpful tips designed to keep you out on the course, instead of in the doctor's office.
Two tips regarding the swing are to rotate the hips and shoulders together, and to avoid bending or hyperextending the spine. If you are not a professional, it might be a good idea to take a lesson or two to improve your swing. It is also important to choose appropriate equipment for your size and skill level.
Several things can be done long before you hit the course to improve conditioning, and proper warming up and stretching will help before each round. Poor fitness and poor flexibility should be worked on to improve endurance and your general health. Strengthening of the core muscles, including the stomach and spine is important in injury prevention. Forearm strengthening is also helpful for the golf game.
Proper warm-up before playing should consist of some type of light exercise to loosen the body, such as brisk walking. Proper stretching should then be done and should include the neck, shoulder, trunk and legs. After stretching, swing practice should be done on the range, or if this is not possible, swinging without a ball should be done. Begin with wedges and then work up through your irons and drivers.


Haha! That's from Jack's video, right? It's a Boy, I think?
I just found this picture -- I've never seen it before!
That is sooo cool, legerdeman! Where did you find it?
Or did you make it?!
Okay prepare for a reg picture overload....I don't recall that I have ever seen any of these posted here before.


From leaking faucets to burst pipes and flooding, water damage is one of the most common and potentially destructive problems you can face as a homeowner. If not taken care of immediately, excess water in your home can promote electrical hazards, cause expensive damage to your home's structure and furnishings, and can even lead to the growth of hazardous mold. When the worst happens, call the experts at ServiceMaster Restore of Old Saybrook, Middletown, and Guilford.
What to do if you're in the middle of a loss?


DREAM LOT WITH ENDLESS DREAM VIEWS of Calgary's stunning skyline! Welcome to 4220 Elbow Drive SW where you have the perfect setting to build your very own MASTERPIECE HOME. Located on a private ridge... overlooking the Lansdowne escarpment, this fabulous lot offers privacy as well as proximity to 'everything that is downtown' while remaining secluded behind the lot's mature trees. You are also surrounded by many "natural" HOTSPOTS including an off-leash dog park, beautiful Stanley Park, and numerous ELBOW RIVER walking pathways. PLEASE VIEW ATTACHED VIDEO TO SEE THIS SPECTACULAR LOT!


text:
Home Coding Not too long, not too short, just right
Not too long, not too short, just right
David A. Frenz, MD
I'LL HIT THE 10-YEAR MARK AS A HOSPITALIST this coming April. Although I'm not exactly an old-timer, I've lived through some of the specialty's major developments. (I've also lost some hair and started to turn grey. There's probably a connection.)
Back in the day, hospitalists were trying to land on a financial model to justify their existence. Hospitals were forking over big bucks to employ us, and it wasn't entirely clear why we were superior to independent community providers who rounded on their own patients for "free."
Hospital length of stay (LOS) turned out to be the lever. We could discharge patients whenever, whereas community providers tended to empty beds in the morning when they rounded before clinic. Hospitalists, it was argued, produced lower lengths of stay, which would improve hospitals' bottom lines.
At first, the evidence was a little scant, but now the LOS differential is pretty clear. A meta-analysis in the Jan. 1, 2012, American Journal of Managed Care, for example, found that hospitalists reduced LOS by at least 0.44 days per case. That's only about 11 hours, but it quickly adds up on an annual basis.
Medicare DRGs
Medicare's current inpatient prospective payment system emerged in the early 1980s as a catalog of diagnosis-related groups (DRGs). Each DRG represents a class of patients, all of whom need similar care and services. Treatment of pneumonia thus became a commodity that Medicare could purchase from any hospital in the country for a specified list price.
For example, "simple pneumonia and pleurisy without complications and comorbidities or major complications and comorbidities" is DRG 195. Medicare anticipates an average LOS of 2.9 days and pays roughly $4,100 per case.
While DRGs are different than the codes we use to bill for our professional services, the two are very much related. Take the patient with a primary diagnosis of pneumococcal pneumonia (ICD-9 code 481). We might submit a charge for a mid-level H&P (E/M code 99222) to be reimbursed for our work. The hospital, in turn, will take that same ICD-9 code and bill for DRG 195 to cover all other aspects of the patient's care.
Why shorter is better
On its face, shorter LOS would seem to be a bad thing. In the hotel industry, for instance, longer LOS juices revenue. Holiday Inn charges by the night, and extending your stay produces a larger bill at check-out.
But Medicare pays a flat rate for each DRG, regardless of LOS. If you can discharge a patient with pneumonia in 1.9 days, your hospital probably makes money because it takes fewer resources to deliver the necessary services in a shorter time. Break-even is around 2.9 days, and beyond that, your hospital risks losing money.
This is why inpatient care managers obsess over LOS. They either want the patient discharged as you approach Medicare's average LOS, or they pester you to add data to the medical record to support a DRG that pays more. For example, "simple pneumonia and pleurisy with complications and comorbidities" (DRG 194) "average LOS of 3.8 days "is worth about $5,700.
"Doctor, doesn't that patient with pneumonia also have COPD?"
Why longer is better
But shorter LOS, while good for hospitals and hospitalists, isn't necessarily great for patients and Medicare. Take decompensated heart failure. While hospitalists might rack up shorter lengths of stay, these patients are readmitted at a dreadfully high rate: 50% or more within six months.
Not surprisingly, Medicare got sick of paying for a fresh DRG for each bounceback and imposed readmission penalties instead. Hospitals have since implemented all sorts of countermeasures: post-discharge telephone calls, better handoffs to ambulatory providers and timely follow-up appointments in outpatient clinics, just to name a few.
I'm a little dubious, mainly because a systematic review in the Oct. 18, 2011, Annals of Internal Medicine found poor underlying evidence for the effectiveness of many of these interventions. The review ultimately concluded that, "No single intervention implemented alone was regularly associated with reduced risk for 30-day rehospitalization."
Maybe it's time for a very counterintuitive solution: increasing length of stay. This seemingly half-baked idea actually has some merit.
In the February 2014 issue of Medical Care Research and Review, Kathleen Carey, PhD, and MengYun Lin, both with Boston University School of Public Health, analyzed a large administrative data set from California for patients with acute myocardial infarction (AMI) and heart failure. Starting with an index hospitalization, the researchers looked at the subsequent rate of readmissions and did some statistical hocus-pocus dealing with LOS. They studied roughly 70,000 cases.
For heart failure and AMI, 30-day readmission rates were 12% and 16% respectively. Increasing LOS by one day reduced the probability of readmission by 6.5% for AMI and 1% for heart failure.
The effect was even more pronounced when the researchers looked at short hospitalizations, defined as a length of stay of seven days or less. Increasing LOS by one day for those hospitalizations reduced the readmission probability for AMI patients during the first week after discharge by a whopping 18%. The corresponding figure for heart failure was 8%.
These data suggest that hospitalists may need to change their posture toward LOS. For some conditions " particularly those with high readmission rates "it might be smarter to keep patients longer. The key is finding the sweet spot between making a buck on shortening LOS and avoiding readmission penalties by increasing it.
What might that spot look like? Let's take garden-variety heart failure (DRG 293, average LOS of 2.6 days), which pays about $3,900 per admission. Suppose your hospitalist group found a way to reduce LOS by 0.25 days, which is about 10% or $390 per case.
But your group also has the opportunity to hold onto patients for one day longer "a 40% increase in LOS that potentially adds $1,500 more to that cost per case. Which is better: shorter or longer?
At first blush, the roughly $1,900 difference would seem to favor shorter LOS. But the math is much more complicated. What if that shorter LOS resulted in a higher readmission rate, while longer LOS reduced bouncebacks? It might be worth the immediate financial hit associated with longer LOS to avoid eventual readmission penalties.
In the end, the answer is probably "both/and." The challenge is finding low-risk cases to discharge sooner and high-risk cases to sit on longer.
I'll let you struggle with how to do this. As for my group, we just went live with a new electronic health record, which promises some sophisticated analytics. The EHR may even lead us to the holy grail: figuring out for this patient with these characteristics on that DRG, what the optimum LOS should be.
David A. Frenz, MD, is a hospitalist for HealthEast Care System in St. Paul, Minn., and is board certified in both family and addiction medicine. You can learn more about him and his work at www.davidfrenz.com or via LinkedIn.
Published in the September 2014 issue of Today's Hospitalist
Discharge rounds redesigned
Hospitalist workforce grew 50% between 2012 and 2019
Phyllis Maguire - January 2023


text:
Keenum on his future: 'Who knows, it might be the Redskins'
Should the Redskins draft Chase Young or trade their pick?
Biggest offseason needs for the Redskins
Chris Simms doesn't expect the Redskins to pursue Cam Newton
Experience made Ron Rivera the most attractive coach
Redskins part ways with Eric Schaffer, hire Rob Rogers
Redskins Subscribe:
Latest Redskins Videos
Redskins Talk Podcast
NFL Mock Draft 3.0
Offseason questions: With Sean McVay gone, will the Redskins run the ball more?
By Rich Tandler February 13, 2017 11:00 AM
The good news for the 2016 Redskins was that they didn't collapse after winning the division the previous season as has been their pattern in the past.
The bad news was that they didn't take the next step and improve from a franchise that can compete to make the playoffs into one that is playing multiple postseason games year in and year out.
That work begins right now for Jay Gruden, Scot McCloughan and the players.
In the coming weeks, Redskins reporters Rich Tandler and JP Finlay will examine the biggest questions facing the Redskins as another offseason gets rolling.
RELATED: LOOKING AT REDSKINS DRAFT PROSPECTS
With Sean McVay gone, will the Redskins run more?
Tandler: You can look at a whole pile of stats that indicate that Sean McVay should have called more running plays in 2016 but let me pull out just a few. When they ran, they did well. They averaged 4.5 yards per rushing attempt, ninth in the NFL and according to the guys at Football Outsiders their rushing game was ranked fourth in DVOA. But they were 21st in rushing yards because they ran only 379 times, 27th in the league.
As the season went on, the press conferences with McVay saying something along the lines of, 'yeah, we should have run it more, it just got away from me' became nearly a weekly affair. Now that McVay is gone and Jay Gruden is taking over the play calling duties, will the Redskins run the ball more often?
Gruden has a reputation for being pass happy but that is not necessarily accurate. His first year here the Redskins averaged 25.1 rushing attempts per game, less than the 26.7 that the league averaged but certainly in the ballpark. Actually, considering that the Redskins were 4-12 and were playing from behind far more often than not, Gruden called runs more often than you might expect him to.
Going back further, Gruden was the Bengals' offensive coordinator for three years and in all three seasons Cincinnati's rushing attempts were very near or above the league average.
With all that said, projecting rushing attempts in 2017 is tricky. It will largely depend on personnel. On one extreme, if both Pierre Garçon and DeSean Jackson return and Kirk Cousins is back in form, Gruden will lean on his passing attack more. If one or both receivers are gone and the Redskins either draft a dynamic back or if Rob Kelley or Matt Jones becomes a top back, Gruden will ground and pound. I'll put the early over/under at 410 attempts, within one or two of the league average.
Finlay: The stats make the case here fairly simple. Washington will run more in 2017 because it would be hard to run much less. For all his strengths, McVay got away from the run far too often.
Perhaps the best example came in a loss at Arizona. Rob Kelley was gashing the Cardinals for 4.5 yards-per-carry, and Chris Thompson had great success to the edge, taking two carries for 24 yards. Yet the 'Skins ran only 16 times in a tight game where Cousins was not his best. The quarterback completed just 56 percent of his passes that day and was under heavy pressure all game.
Speaking with 'Skins coaches, expect Kelley to get the opprotunity to cement his role as the No. 1 runner. And expect the offense to give him the ball more.
More offseason questions:
—What are resonable expectations for Josh Doctson?
— Will there be a surprise salary cap cut?
— Should the Redskins defense switch to the 4-3?
— Is Spencer Long the answer at center?
— How many D-linemen do the Redskins need?
Want more Redskins? Check out @JPFinlayCSN and @Rich_TandlerCSN for live updates or click here for the #RedskinsTalk Podcast on iTunes, here for Google Play or press play below. Don't forget to subscribe!
Tags: Latest Headlines, Real Redskins, Redskins Top Stories
Report: Bill Callahan to join Browns' staff as offensive line coach
By Ethan Cadeaux January 20, 2020 5:30 PM
Bill Callahan was not unemployed for long.
The former Redskins offensive line coach, who served as Washington's interim head coach in 2019 after Jay Gruden was fired following an 0-5 start, is joining the Cleveland Browns staff, according to NFL Network's Tom Pelissero.
The #Browns are expected to hire Bill Callahan to coach their offensive line, sources say. Important addition of a former head coach for Kevin Stefanski's staff.
— Tom Pelissero (@TomPelissero) January 20, 2020
The 63-year-old will reportedly serve as the Browns' offensive line coach, a title he has over two decades of coaching experience of.
Callahan served as the Redskins offensive line coach from 2017-2019. He worked his way up the coaching ranks in both college and the NFL as an offensive line coach for over a decade before the Raiders hired him as offensive coordinator in 1998. He was later promoted to head coach in 2002 and spent two seasons at the helm before leaving for the same position at Nebraska.
After a four-year tenure as head coach at the University of Nebraska ended in 2007, Callahan returned to the NFL as an offensive line coach for the Jets. He spent the next 12 years as an offensive line coach for three different NFL teams before he was named the Redskins interim head coach in October.
MORE REDSKINS NEWS:
Winning the Job: How Turner was named OC
The Return: Gruden interviewing for Jags OC
Kuechly to DC?: Would Rivera hire him?
Scott Turner won the Redskins offensive coordinator job over Kevin O'Connell, per source
By JP Finlay January 20, 2020 7:30 AM
There has been plenty of speculation as to why new Redskins head coach Ron Rivera decided to hire Scott Turner as offensive coordinator, and now a source tells NBC Sports Washington the answer is simple.
Turner won the job competition.
Many expected 2019 Redskins offensive coordinator Kevin O'Connell to maintain his position when the team hired Rivera as their new head coach earlier this month. That didn't happen.
As Rivera moved quickly to assemble his coaching staff, the biggest question seemed to be running the offense and working with second-year quarterback Dwayne Haskins. Rivera interviewed O'Connell and Turner for the job, and asked to interview former Giants head coach Pat Shurmur.
Shurmur declined the interview, and at that point, a source explained that Rivera then made his decision to go with Turner over O'Connell.
So why Turner?
Both candidates got their first experience calling plays last year after an in-season firing to the head coach. The results weren't great for either coach, but Turner's game plans involved more play action passing than O'Connell.
Turner's resume working with Cam Newton and Teddy Bridgewater mattered, as did the plan Turner presented for working with Haskins.
It's important to note that Rivera had years of experience working with Turner, as well as his father Norv Turner. That mattered too, and one source explained Rivera "believed" in Turner.
While O'Connell landed in a strong spot as offensive coordinator for the Rams, he won't be calling plays. Coaches don't like giving up control, particularly offensive coaches giving up play calling. For O'Connell, maybe that will change in LA, but it will take time.
Some Redskins fans have a bad habit of assuming the worst. That maybe Turner got the job because O'Connell passed on it. That's not the case, per multiple sources.
Ron Rivera wanted his guy, and that's why Turner got the job.
The Return: Jay Gruden interviewing for Jags OC position
Kuechly to DC?: Would Ron Rivera hire his former player?
Staying in NFC East: Garrett named new Giants OC
Report: Bill Callahan to join Browns' staff as offensive line coach Scott Turner won the Redskins offensive coordinator job over Kevin O'Connell, per source Report: Months after major leg injury, Reuben Foster regains feeling in toes Report: Jay Gruden interviewing for Jaguars offensive coordinator job If Luke Kuechly wants to coach, would Ron Rivera hire him for the Redskins? Jason Garrett reportedly to stay in NFC East, becomes Giants offensive coordinator DeAngelo Hall defends cornerback Josh Norman, but believes Redskins should move on Wait, what? Report says Bill Belichick 'inquired' about coaching the Redskins 3 critical takeaways from Jack Del Rio's first media session as Redskins defensive coordinator 3 critical takeaways from Scott Turner's first media session as Redskins offensive coordinator 2020 NFL Mock Draft 10.0: Will Isaiah Simmons jump Chase Young? When watching the Redskins, Jack Del Rio sees 'countless examples' of poor communication Scott Turner is high on Dwayne Haskins and needs QB to be 'most committed' guy in building Redskins officially announce near complete overhaul to Ron Rivera's coaching staff How the 49ers are proof that the Redskins should absolutely draft Chase Young Rooney Rule to be examined after Redskins' Ron Rivera the only minority head coach hired Dwayne Haskins, Ron Rivera react to shocking retirement announcement from Luke Kuechly Here's a clear picture of the Redskins' new power structure in the Ron Rivera era Why Chris Simms thinks the Redskins shouldn't go after Cam Newton Here are important NFL offseason dates Redskins fans should know


On the chilly morning of November 9th, a conference room filled to the brim with artists, designers, and makers embarked on an important conversation: sustainability in fashion + textiles. I settled down into my seat only to discover that I sat next to the mother of the keynote speaker, Rhett Godfrey – Sustainability Director of Loomstate, whom smiled and took a copious amount of pictures of her son during his talk.
I sat there as Bob Bland, the CEO + Founder of Manufacture New York welcomed all of us – designers, artists, and leaders of the sustainability movement.
I never thought about sustainability much. I mean, we are taught to consume and put money into the economy (which is good of course), but we only ever focus on the end product. Where did your sweater come from? Who made your shirt or your shoes? We don't think about these things…we don't have to think about these things. Yet, when terrifyingly tragic incidents occur, like the ones in Bangladesh, we are forced to think about what it means to live sustainably. The point of this summit is to bring together a collective of likeminded people – designers and artists whom share a common passion for textiles + fashion, while also treating the industry + those who create our wares with the respect they deserve, like the artisans they are.
If the Bangladesh incidents happened in the US, we wouldn't let that go down without a fight, so why do we sit here content with ourselves as they happen across the ocean? Our culture of consumerism was created by us, we created the "need" for Walmart and "fast-fashion" but it's time we stop. It's time to take that last shred of fast-fashion and throw it out with yesterday's news. Every day there are people who are pushing to make the fashion industry catch up with the ideals of other industries, like food. If you think about it, if eating organic is important to you, then shouldn't wearing organic matter? Shouldn't we be supporting labels and companies who put more money into their workers and villages where warehouses are located rather than CEO pockets? Currently, even H&M is reviewing what they can do to raise wages for textile workers in Bangladesh and in technology news, Apple is pushing for Made in America with their new Mac Pro model…now it's time for others to follow suit.
After the speakers and panelist discussions, we were invited back to Manufacture NY's space for drinks, networking, and small workshops. Textile Arts Center was there to teach folks about natural dyeing with indigo!
Our very good friend (and a current Resident Artist) Zaida of BALMASEDA was there to meet and greet folks, sharing her fantastic pieces!
It was such a great event; there were tons of people there with one common goal: uniting small labels + designers who are pushing the envelope of sustainability and fashion. I cannot wait to see what happens in the future with these summits and what Manufacture New York has in store.
Do you have any thoughts of ideas of how we could move towards a more sustainable fashion industry? Leave a comment below!


text:
/*************************************************************************/
/* Copyright (c) 2004                                                    */
/* Daniel Sleator, David Temperley, and John Lafferty                    */
/* All rights reserved                                                   */
/*                                                                       */
/* Use of the link grammar parsing system is subject to the terms of the */
/* license set forth in the LICENSE file included with this software,    */
/* and also available at http://www.link.cs.cmu.edu/link/license.html    */
/* This license allows free redistribution and use in source and binary  */
/* forms, with or without modification, subject to certain conditions.   */
/*                                                                       */
/*************************************************************************/

 /* see bottom of file for comments on post processing */

#include <stdarg.h>
#include <memory.h>
#include <link-grammar/api.h>

#define PP_MAX_DOMAINS 128

/***************** utility routines (not exported) ***********************/

static int string_in_list(const char * s, char * a[])
{
	/* returns FALSE if the string s does not match anything in
		 the array.	The array elements are post-processing symbols */
	int i;
	for (i=0; a[i] != NULL; i++)
		if (post_process_match(a[i], s)) return TRUE;
	return FALSE;
}

static int find_domain_name(Postprocessor *pp, const char *link)
{
	/* Return the name of the domain associated with the provided starting
		 link. Return -1 if link isn't associated with a domain. */
	int i,domain;
	StartingLinkAndDomain *sllt = pp->knowledge->starting_link_lookup_table;
	for (i=0;;i++)
		{
			domain = sllt[i].domain;
			if (domain==-1) return -1;					/* hit the end-of-list sentinel */
			if (post_process_match(sllt[i].starting_link, link)) return domain;
		}
}

static int contained_in(Domain * d1, Domain * d2, Sublinkage *sublinkage)
{
	/* returns TRUE if domain d1 is contained in domain d2 */
	char mark[MAX_LINKS];
	List_o_links * lol;
	memset(mark, 0, sublinkage->num_links*(sizeof mark[0]));
	for (lol=d2->lol; lol != NULL; lol = lol->next)
		mark[lol->link] = TRUE;
	for (lol=d1->lol; lol != NULL; lol = lol->next)
		if (!mark[lol->link]) return FALSE;
	return TRUE;
}

static int link_in_domain(int link, Domain * d)
{
	/* returns the predicate "the given link is in the given domain" */
	List_o_links * lol;
	for (lol = d->lol; lol != NULL; lol = lol->next)
		if (lol->link == link) return TRUE;
	return FALSE;
}

/* #define CHECK_DOMAIN_NESTING */

#if defined(CHECK_DOMAIN_NESTING)
/* Although this is no longer used, I'm leaving the code here for future reference --DS 3/98 */

static int check_domain_nesting(Postprocessor *pp, int num_links)
{
	/* returns TRUE if the domains actually form a properly nested structure */
	Domain * d1, * d2;
	int counts[4];
	char mark[MAX_LINKS];
	List_o_links * lol;
	int i;
	for (d1=pp->pp_data.domain_array; d1 < pp->pp_data.domain_array + pp->pp_data.N_domains; d1++) {
		for (d2=d1+1; d2 < pp->pp_data.domain_array + pp->pp_data.N_domains; d2++) {
			memset(mark, 0, num_links*(sizeof mark[0]));
			for (lol=d2->lol; lol != NULL; lol = lol->next) {
		mark[lol->link] = 1;
			}
			for (lol=d1->lol; lol != NULL; lol = lol->next) {
		mark[lol->link] += 2;
			}
			counts[0] = counts[1] = counts[2] = counts[3] = 0;
			for (i=0; i<num_links; i++)
		counts[(int)mark[i]]++;/* (int) cast avoids compiler warning DS 7/97 */
			if ((counts[1] > 0) && (counts[2] > 0) && (counts[3] > 0))
		return FALSE;
		}
	}
	return TRUE;
}
#endif

/**
 * Free the list of links pointed to by lol
 * (does not free any strings)
 */
static void free_List_o_links(List_o_links *lol)
{
	List_o_links * xlol;
	while(lol != NULL) {
		xlol = lol->next;
		xfree(lol, sizeof(List_o_links));
		lol = xlol;
	}
}

static void free_D_tree_leaves(DTreeLeaf *dtl)
{
	DTreeLeaf * xdtl;
	while(dtl != NULL) {
		xdtl = dtl->next;
		xfree(dtl, sizeof(DTreeLeaf));
		dtl = xdtl;
	}
}

/**
 * Gets called after every invocation of post_process()
 */
void post_process_free_data(PP_data * ppd)
{
	int w, d;
	for (w = 0; w < ppd->length; w++)
	{
		free_List_o_links(ppd->word_links[w]);
		ppd->word_links[w] = NULL;
	}
	for (d = 0; d < ppd->N_domains; d++)
	{
		free_List_o_links(ppd->domain_array[d].lol);
		ppd->domain_array[d].lol = NULL;
		free_D_tree_leaves(ppd->domain_array[d].child);
		ppd->domain_array[d].child = NULL;
	}
	free_List_o_links(ppd->links_to_ignore);
	ppd->links_to_ignore = NULL;
}

static void connectivity_dfs(Postprocessor *pp, Sublinkage *sublinkage,
                             int w, pp_linkset *ls)
{
	List_o_links *lol;
	pp->visited[w] = TRUE;
	for (lol = pp->pp_data.word_links[w]; lol != NULL; lol = lol->next)
	{
		if (!pp->visited[lol->word] &&
				!pp_linkset_match(ls, sublinkage->link[lol->link]->name))
			connectivity_dfs(pp, sublinkage, lol->word, ls);
	}
}

static void mark_reachable_words(Postprocessor *pp, int w)
{
	List_o_links *lol;
	if (pp->visited[w]) return;
	pp->visited[w] = TRUE;
	for (lol = pp->pp_data.word_links[w]; lol != NULL; lol = lol->next)
		mark_reachable_words(pp, lol->word);
}

static int is_connected(Postprocessor *pp)
{
	/* Returns true if the linkage is connected, considering words
		 that have at least one edge....this allows conjunctive sentences
		 not to be thrown out. */
	int i;
	for (i=0; i<pp->pp_data.length; i++)
		pp->visited[i] = (pp->pp_data.word_links[i] == NULL);
	mark_reachable_words(pp, 0);
	for (i=0; i<pp->pp_data.length; i++)
		if (!pp->visited[i]) return FALSE;
	return TRUE;
}

static void build_type_array(Postprocessor *pp)
{
	D_type_list * dtl;
	int d;
	List_o_links * lol;
	for (d=0; d<pp->pp_data.N_domains; d++)
	{
		for (lol=pp->pp_data.domain_array[d].lol; lol != NULL; lol = lol->next)
		{
			dtl = (D_type_list *) xalloc(sizeof(D_type_list));
			dtl->next = pp->pp_node->d_type_array[lol->link];
			pp->pp_node->d_type_array[lol->link] = dtl;
			dtl->type = pp->pp_data.domain_array[d].type;
		}
	}
}

void free_d_type(D_type_list * dtl)
{
	D_type_list * dtlx;
	for (; dtl!=NULL; dtl=dtlx) {
		dtlx = dtl->next;
		xfree((void*) dtl, sizeof(D_type_list));
	}
}

D_type_list * copy_d_type(D_type_list * dtl)
{
	D_type_list *dtlx, *dtlcurr=NULL, *dtlhead=NULL;
	for (; dtl!=NULL; dtl=dtl->next)
	{
		dtlx = (D_type_list *) xalloc(sizeof(D_type_list));
		*dtlx = *dtl;
		if (dtlhead == NULL)
		{
			dtlhead = dtlx;
			dtlcurr = dtlx;
		}
		else
		{
			dtlcurr->next = dtlx;
			dtlcurr = dtlx;
		}
	}
	return dtlhead;
}

/** free the pp node from last time */
static void free_pp_node(Postprocessor *pp)
{
	int i;
	PP_node *ppn = pp->pp_node;
	pp->pp_node = NULL;
	if (ppn == NULL) return;

	for (i=0; i<MAX_LINKS; i++)
	{
		free_d_type(ppn->d_type_array[i]);
	}
	xfree((void*) ppn, sizeof(PP_node));
}

/** set up a fresh pp_node for later use */
static void alloc_pp_node(Postprocessor *pp)
{
	int i;
	pp->pp_node=(PP_node *) xalloc(sizeof(PP_node));
	pp->pp_node->violation = NULL;
	for (i=0; i<MAX_LINKS; i++)
		pp->pp_node->d_type_array[i] = NULL;
}

static void reset_pp_node(Postprocessor *pp)
{
	free_pp_node(pp);
	alloc_pp_node(pp);
}

/************************ rule application *******************************/

static int apply_rules(Postprocessor *pp,
							 int (applyfn) (Postprocessor *,Sublinkage *,pp_rule *),
							 Sublinkage *sublinkage,
							 pp_rule *rule_array,
							 char **msg)
{
	int i;
	for (i=0; (*msg=rule_array[i].msg)!=NULL; i++)
		if (!applyfn(pp, sublinkage, &(rule_array[i]))) return 0;
	return 1;
}

static int
apply_relevant_rules(Postprocessor *pp,
						 int(applyfn)(Postprocessor *pp,Sublinkage*,pp_rule *rule),
						 Sublinkage *sublinkage,
						 pp_rule *rule_array,
						 int *relevant_rules,
						 char **msg)
{
	int i, idx;

	/* if we didn't accumulate link names for this sentence, we need to apply
		 all rules */
	if (pp_linkset_population(pp->set_of_links_of_sentence)==0) {
			return apply_rules(pp, applyfn, sublinkage, rule_array, msg);
	}

	/* we did, and we don't */
	for (i=0; (idx=relevant_rules[i])!=-1; i++) {
			*msg = rule_array[idx].msg;	 /* Adam had forgotten this -- DS 4/9/98 */
			if (!applyfn(pp, sublinkage, &(rule_array[idx]))) return 0;
	}
	return 1;
}

static int
apply_contains_one(Postprocessor *pp, Sublinkage *sublinkage, pp_rule *rule)
{
	/* returns TRUE if and only if all groups containing the specified link
		 contain at least one from the required list.	(as determined by exact
		 string matching) */
	DTreeLeaf * dtl;
	int d, count;
	for (d=0; d<pp->pp_data.N_domains; d++)
		{
			for (dtl = pp->pp_data.domain_array[d].child;
			 dtl != NULL &&
				 !post_process_match(rule->selector,
								 sublinkage->link[dtl->link]->name);
			 dtl = dtl->next);
			if (dtl != NULL)
		{
			/* selector link of rule appears in this domain */
			count=0;
			for (dtl = pp->pp_data.domain_array[d].child; dtl != NULL; dtl = dtl->next)
				if (string_in_list(sublinkage->link[dtl->link]->name,
									 rule->link_array))
					{
				count=1;
				break;
					}
			if (count == 0) return FALSE;
		}
		}
	return TRUE;
}

static int
apply_contains_none(Postprocessor *pp,Sublinkage *sublinkage,pp_rule *rule)
{
	/* returns TRUE if and only if:
		 all groups containing the selector link do not contain anything
		 from the link_array contained in the rule. Uses exact string matching. */
	DTreeLeaf * dtl;
	int d;
	for (d=0; d<pp->pp_data.N_domains; d++)
		{
			for (dtl = pp->pp_data.domain_array[d].child;
			 dtl != NULL &&
				 !post_process_match(rule->selector,
								 sublinkage->link[dtl->link]->name);
			 dtl = dtl->next);
			if (dtl != NULL)
		{
			/* selector link of rule appears in this domain */
			for (dtl = pp->pp_data.domain_array[d].child; dtl != NULL; dtl = dtl->next)
				if (string_in_list(sublinkage->link[dtl->link]->name,
									 rule->link_array))
					return FALSE;
		}
		}
	return TRUE;
}

static int
apply_contains_one_globally(Postprocessor *pp,Sublinkage *sublinkage,pp_rule *rule)
{
	/* returns TRUE if and only if
		 (1) the sentence doesn't contain the selector link for the rule, or
		 (2) it does, and it also contains one or more from the rule's link set */

	int i,j,count;
	for (i=0; i<sublinkage->num_links; i++) {
		if (sublinkage->link[i]->l == -1) continue;
		if (post_process_match(rule->selector,sublinkage->link[i]->name)) break;
	}
	if (i==sublinkage->num_links) return TRUE;

	/* selector link of rule appears in sentence */
	count=0;
	for (j=0; j<sublinkage->num_links && count==0; j++) {
		if (sublinkage->link[j]->l == -1) continue;
		if (string_in_list(sublinkage->link[j]->name, rule->link_array))
			{
		count=1;
		break;
			}
	}
	if (count==0) return FALSE; else return TRUE;
}

static int
apply_connected(Postprocessor *pp, Sublinkage *sublinkage, pp_rule *rule)
{
	/* There is actually just one (or none, if user didn't specify it)
		 rule asserting that linkage is connected. */
	if (!is_connected(pp)) return 0;
	return 1;
}

#if 0
/* replaced in 3/98 with a slightly different algorithm shown below	---DS*/
static int
apply_connected_without(Postprocessor *pp,Sublinkage *sublinkage,pp_rule *rule)
{
	/* Returns true if the linkage is connected when ignoring the links
		 whose names are in the given list of link names.
		 Actually, what it does is this: it returns FALSE if the connectivity
		 of the subgraph reachable from word 0 changes as a result of deleting
		 these links. */
	int i;
	memset(pp->visited, 0, pp->pp_data.length*(sizeof pp->visited[0]));
	mark_reachable_words(pp, 0);
	for (i=0; i<pp->pp_data.length; i++)
		pp->visited[i] = !pp->visited[i];
	connectivity_dfs(pp, sublinkage, 0, rule->link_set);
	for (i=0; i<pp->pp_data.length; i++)
		if (pp->visited[i] == FALSE) return FALSE;
	return TRUE;
}
#else

/* Here's the new algorithm: For each link in the linkage that is in the
	 must_form_a_cycle list, we want to make sure that that link
	 is in a cycle.	We do this simply by deleting the link, then seeing if the
	 end points of that link are still connected.
*/

static void reachable_without_dfs(Postprocessor *pp, Sublinkage *sublinkage, int a, int b, int w) {
		 /* This is a depth first search of words reachable from w, excluding any direct edge
		between word a and word b. */
		List_o_links *lol;
		pp->visited[w] = TRUE;
		for (lol = pp->pp_data.word_links[w]; lol != NULL; lol = lol->next) {
		if (!pp->visited[lol->word] && !(w == a && lol->word == b) && ! (w == b && lol->word == a)) {
				reachable_without_dfs(pp, sublinkage, a, b, lol->word);
		}
		}
}

/**
 * Returns TRUE if the linkage is connected when ignoring the links
 * whose names are in the given list of link names.
 * Actually, what it does is this: it returns FALSE if the connectivity
 * of the subgraph reachable from word 0 changes as a result of deleting
 * these links.
 */
static int
apply_must_form_a_cycle(Postprocessor *pp,Sublinkage *sublinkage,pp_rule *rule)
{
	List_o_links *lol;
	int w;
	for (w=0; w<pp->pp_data.length; w++) {
		for (lol = pp->pp_data.word_links[w]; lol != NULL; lol = lol->next) {
				if (w > lol->word) continue;	/* only consider each edge once */
				if (!pp_linkset_match(rule->link_set, sublinkage->link[lol->link]->name)) continue;
				memset(pp->visited, 0, pp->pp_data.length*(sizeof pp->visited[0]));
				reachable_without_dfs(pp, sublinkage, w, lol->word, w);
				if (!pp->visited[lol->word]) return FALSE;
		}
	}

	for (lol = pp->pp_data.links_to_ignore; lol != NULL; lol = lol->next) {
		w = sublinkage->link[lol->link]->l;
		/* (w, lol->word) are the left and right ends of the edge we're considering */
		if (!pp_linkset_match(rule->link_set, sublinkage->link[lol->link]->name)) continue;
		memset(pp->visited, 0, pp->pp_data.length*(sizeof pp->visited[0]));
		reachable_without_dfs(pp, sublinkage, w, lol->word, w);
		if (!pp->visited[lol->word]) return FALSE;
	}

	return TRUE;
}

#endif

static int
apply_bounded(Postprocessor *pp,Sublinkage *sublinkage,pp_rule *rule)
{
	/* Checks to see that all domains with this name have the property that
		 all of the words that touch a link in the domain are not to the left
		 of the root word of the domain. */
	int d, lw, d_type;
	List_o_links * lol;
	d_type = rule->domain;
	for (d=0; d<pp->pp_data.N_domains; d++) {
		if (pp->pp_data.domain_array[d].type != d_type) continue;
		lw = sublinkage->link[pp->pp_data.domain_array[d].start_link]->l;
		for (lol = pp->pp_data.domain_array[d].lol; lol != NULL; lol = lol->next) {
			if (sublinkage->link[lol->link]->l < lw) return FALSE;
		}
	}
	return TRUE;
}

/********************* various non-exported functions ***********************/

static void build_graph(Postprocessor *pp, Sublinkage *sublinkage)
{
	/* fill in the pp->pp_data.word_links array with a list of words neighboring each
		 word (actually a list of links).	The dir fields are not set, since this
		 (after fat-link-extraction) is an undirected graph. */
	int i, link;
	List_o_links * lol;

	for (i=0; i<pp->pp_data.length; i++)
		pp->pp_data.word_links[i] = NULL;

	for (link=0; link<sublinkage->num_links; link++)
		{
			if (sublinkage->link[link]->l == -1) continue;
			if (pp_linkset_match(pp->knowledge->ignore_these_links, sublinkage->link[link]->name)) {
			lol = (List_o_links *) xalloc(sizeof(List_o_links));
			lol->next = pp->pp_data.links_to_ignore;
			pp->pp_data.links_to_ignore = lol;
			lol->link = link;
			lol->word = sublinkage->link[link]->r;
			continue;
			}

			lol = (List_o_links *) xalloc(sizeof(List_o_links));
			lol->next = pp->pp_data.word_links[sublinkage->link[link]->l];
			pp->pp_data.word_links[sublinkage->link[link]->l] = lol;
			lol->link = link;
			lol->word = sublinkage->link[link]->r;

			lol = (List_o_links *) xalloc(sizeof(List_o_links));
			lol->next = pp->pp_data.word_links[sublinkage->link[link]->r];
			pp->pp_data.word_links[sublinkage->link[link]->r] = lol;
			lol->link = link;
			lol->word = sublinkage->link[link]->l;
		}
}

static void setup_domain_array(Postprocessor *pp,
									 int n, const char *string, int start_link)
{
	/* set pp->visited[i] to FALSE */
	memset(pp->visited, 0, pp->pp_data.length*(sizeof pp->visited[0]));
	pp->pp_data.domain_array[n].string = string;
	pp->pp_data.domain_array[n].lol    = NULL;
	pp->pp_data.domain_array[n].size   = 0;
	pp->pp_data.domain_array[n].start_link = start_link;
}

static void add_link_to_domain(Postprocessor *pp, int link)
{
	List_o_links *lol;
	lol = (List_o_links *) xalloc(sizeof(List_o_links));
	lol->next = pp->pp_data.domain_array[pp->pp_data.N_domains].lol;
	pp->pp_data.domain_array[pp->pp_data.N_domains].lol = lol;
	pp->pp_data.domain_array[pp->pp_data.N_domains].size++;
	lol->link = link;
}

static void depth_first_search(Postprocessor *pp, Sublinkage *sublinkage,
									 int w, int root,int start_link)
{
	List_o_links *lol;
	pp->visited[w] = TRUE;
	for (lol = pp->pp_data.word_links[w]; lol != NULL; lol = lol->next) {
		if (lol->word < w && lol->link != start_link) {
			add_link_to_domain(pp, lol->link);
		}
	}
	for (lol = pp->pp_data.word_links[w]; lol != NULL; lol = lol->next) {
		if (!pp->visited[lol->word] && (lol->word != root) &&
		!(lol->word < root && lol->word < w &&
					pp_linkset_match(pp->knowledge->restricted_links,
							 sublinkage->link[lol->link]->name)))
			depth_first_search(pp, sublinkage, lol->word, root, start_link);
	}
}

static void bad_depth_first_search(Postprocessor *pp, Sublinkage *sublinkage,
									 int w, int root, int start_link)
{
	List_o_links * lol;
	pp->visited[w] = TRUE;
	for (lol = pp->pp_data.word_links[w]; lol != NULL; lol = lol->next) {
		if ((lol->word < w)	&& (lol->link != start_link) && (w != root)) {
			add_link_to_domain(pp, lol->link);
		}
	}
	for (lol = pp->pp_data.word_links[w]; lol != NULL; lol = lol->next) {
		if ((!pp->visited[lol->word]) && !(w == root && lol->word < w) &&
		!(lol->word < root && lol->word < w &&
					pp_linkset_match(pp->knowledge->restricted_links,
							 sublinkage->link[lol->link]->name)))
			bad_depth_first_search(pp, sublinkage, lol->word, root, start_link);
	}
}

static void d_depth_first_search(Postprocessor *pp, Sublinkage *sublinkage,
								 int w, int root, int right, int start_link)
{
	List_o_links * lol;
	pp->visited[w] = TRUE;
	for (lol = pp->pp_data.word_links[w]; lol != NULL; lol = lol->next) {
		if ((lol->word < w) && (lol->link != start_link) && (w != root)) {
			add_link_to_domain(pp, lol->link);
		}
	}
	for (lol = pp->pp_data.word_links[w]; lol != NULL; lol = lol->next) {
		if (!pp->visited[lol->word] && !(w == root && lol->word >= right) &&
		!(w == root && lol->word < root) &&
		!(lol->word < root && lol->word < w &&
					pp_linkset_match(pp->knowledge->restricted_links,
							 sublinkage->link[lol->link]->name)))
			d_depth_first_search(pp,sublinkage,lol->word,root,right,start_link);
	}
}

static void left_depth_first_search(Postprocessor *pp, Sublinkage *sublinkage,
															 int w, int right,int start_link)
{
	List_o_links *lol;
	pp->visited[w] = TRUE;
	for (lol = pp->pp_data.word_links[w]; lol != NULL; lol = lol->next) {
		if (lol->word < w && lol->link != start_link) {
			add_link_to_domain(pp, lol->link);
		}
	}
	for (lol = pp->pp_data.word_links[w]; lol != NULL; lol = lol->next) {
		if (!pp->visited[lol->word] && (lol->word != right))
			depth_first_search(pp, sublinkage, lol->word, right, start_link);
	}
}

static int domain_compare(const Domain * d1, const Domain * d2)
{ return (d1->size-d2->size); /* for sorting the domains by size */ }

static void build_domains(Postprocessor *pp, Sublinkage *sublinkage)
{
	int link, i, d;
	const char *s;
	pp->pp_data.N_domains = 0;

	for (link = 0; link<sublinkage->num_links; link++) {
		if (sublinkage->link[link]->l == -1) continue;
		s = sublinkage->link[link]->name;

		if (pp_linkset_match(pp->knowledge->ignore_these_links, s)) continue;
		if (pp_linkset_match(pp->knowledge->domain_starter_links, s))
			{
		setup_domain_array(pp, pp->pp_data.N_domains, s, link);
				if (pp_linkset_match(pp->knowledge->domain_contains_links, s))
			add_link_to_domain(pp, link);
		depth_first_search(pp,sublinkage,sublinkage->link[link]->r,
							 sublinkage->link[link]->l, link);

		pp->pp_data.N_domains++;
				assert(pp->pp_data.N_domains<PP_MAX_DOMAINS, "raise value of PP_MAX_DOMAINS");
			}
		else {
			if (pp_linkset_match(pp->knowledge->urfl_domain_starter_links,s))
		{
			setup_domain_array(pp, pp->pp_data.N_domains, s, link);
			/* always add the starter link to its urfl domain */
			add_link_to_domain(pp, link);
			bad_depth_first_search(pp,sublinkage,sublinkage->link[link]->r,
								 sublinkage->link[link]->l,link);
			pp->pp_data.N_domains++;
			assert(pp->pp_data.N_domains<PP_MAX_DOMAINS,"raise PP_MAX_DOMAINS value");
		}
			else
		if (pp_linkset_match(pp->knowledge->urfl_only_domain_starter_links,s))
			{
				setup_domain_array(pp, pp->pp_data.N_domains, s, link);
				/* do not add the starter link to its urfl_only domain */
				d_depth_first_search(pp,sublinkage, sublinkage->link[link]->l,
								 sublinkage->link[link]->l,
								 sublinkage->link[link]->r,link);
				pp->pp_data.N_domains++;
				assert(pp->pp_data.N_domains<PP_MAX_DOMAINS,"raise PP_MAX_DOMAINS value");
			}
		else
			if (pp_linkset_match(pp->knowledge->left_domain_starter_links,s))
				{
					setup_domain_array(pp, pp->pp_data.N_domains, s, link);
					/* do not add the starter link to a left domain */
					left_depth_first_search(pp,sublinkage, sublinkage->link[link]->l,
									 sublinkage->link[link]->r,link);
					pp->pp_data.N_domains++;
					assert(pp->pp_data.N_domains<PP_MAX_DOMAINS,"raise PP_MAX_DOMAINS value");
				}
		}
	}

	/* sort the domains by size */
	qsort((void *) pp->pp_data.domain_array,
		pp->pp_data.N_domains,
		sizeof(Domain),
		(int (*)(const void *, const void *)) domain_compare);

	/* sanity check: all links in all domains have a legal domain name */
	for (d=0; d<pp->pp_data.N_domains; d++) {
		i = find_domain_name(pp, pp->pp_data.domain_array[d].string);
		if (i==-1)
			 error("\tpost_process: Need an entry for %s in LINK_TYPE_TABLE",
					 pp->pp_data.domain_array[d].string);
		pp->pp_data.domain_array[d].type = i;
	}
}

static void build_domain_forest(Postprocessor *pp, Sublinkage *sublinkage)
{
	int d, d1, link;
	DTreeLeaf * dtl;
	if (pp->pp_data.N_domains > 0)
		pp->pp_data.domain_array[pp->pp_data.N_domains-1].parent = NULL;
	for (d=0; d < pp->pp_data.N_domains-1; d++) {
		for (d1 = d+1; d1 < pp->pp_data.N_domains; d1++) {
			if (contained_in(&pp->pp_data.domain_array[d],&pp->pp_data.domain_array[d1],sublinkage))
		{
			pp->pp_data.domain_array[d].parent = &pp->pp_data.domain_array[d1];
			break;
		}
		}
		if (d1 == pp->pp_data.N_domains) {
			/* we know this domain is a root of a new tree */
			pp->pp_data.domain_array[d].parent = NULL;
			/* It's now ok for this to happen.	It used to do:
		 printf("I can't find a parent domain for this domain\n");
		 print_domain(d);
		 exit(1); */
		}
	}
	/* the parent links of domain nodes have been established.
		 now do the leaves */
	for (d=0; d < pp->pp_data.N_domains; d++) {
		pp->pp_data.domain_array[d].child = NULL;
	}
	for (link=0; link < sublinkage->num_links; link++) {
		if (sublinkage->link[link]->l == -1) continue; /* probably not necessary */
		for (d=0; d<pp->pp_data.N_domains; d++) {
			if (link_in_domain(link, &pp->pp_data.domain_array[d])) {
		dtl = (DTreeLeaf *) xalloc(sizeof(DTreeLeaf));
		dtl->link = link;
		dtl->parent = &pp->pp_data.domain_array[d];
		dtl->next = pp->pp_data.domain_array[d].child;
		pp->pp_data.domain_array[d].child = dtl;
		break;
			}
		}
	}
}

static int
internal_process(Postprocessor *pp,Sublinkage *sublinkage,char **msg)
{
	int i;
	/* quick test: try applying just the relevant global rules */
	if (!apply_relevant_rules(pp,apply_contains_one_globally,
								sublinkage,
								pp->knowledge->contains_one_rules,
								pp->relevant_contains_one_rules, msg)) {
		for (i=0; i<pp->pp_data.length; i++)
			pp->pp_data.word_links[i] = NULL;
		pp->pp_data.N_domains = 0;
		return -1;
	}

	/* build graph; confirm that it's legally connected */
	build_graph(pp, sublinkage);
	build_domains(pp, sublinkage);
	build_domain_forest(pp, sublinkage);

#if defined(CHECK_DOMAIN_NESTING)
	/* These messages were deemed to not be useful, so
		 this code is commented out.	See comment above. */
	if(!check_domain_nesting(pp, sublinkage->num_links))
			printf("WARNING: The domains are not nested.\n");
#endif

	/* The order below should be optimal for most cases */
	if (!apply_relevant_rules(pp,apply_contains_one, sublinkage,
								pp->knowledge->contains_one_rules,
								pp->relevant_contains_one_rules, msg))	return 1;
	if (!apply_relevant_rules(pp,apply_contains_none, sublinkage,
								pp->knowledge->contains_none_rules,
									pp->relevant_contains_none_rules, msg)) return 1;
	if (!apply_rules(pp,apply_must_form_a_cycle, sublinkage,
					 pp->knowledge->form_a_cycle_rules,msg))		 return 1;
	if (!apply_rules(pp,apply_connected, sublinkage,
					 pp->knowledge->connected_rules, msg))						return 1;
	if (!apply_rules(pp,apply_bounded, sublinkage,
					 pp->knowledge->bounded_rules, msg))							return 1;
	return 0; /* This linkage satisfied all the rules */
}

static void prune_irrelevant_rules(Postprocessor *pp)
{
	/* call this (a) after having called post_process_scan_linkage() on all
		 generated linkages, but (b) before calling post_process() on any
		 particular linkage. Here we mark all rules which we know (from having
		 accumulated a set of link names appearing in *any* linkage) won't
		 ever be needed. */
	 pp_rule *rule;
	 int coIDX, cnIDX, rcoIDX=0, rcnIDX=0;

	/* If we didn't scan any linkages, there's no pruning to be done. */
	if (pp_linkset_population(pp->set_of_links_of_sentence)==0) return;

	for (coIDX=0;;coIDX++)
		 {
			 rule = &(pp->knowledge->contains_one_rules[coIDX]);
			 if (rule->msg==NULL) break;
			 if (pp_linkset_match_bw(pp->set_of_links_of_sentence, rule->selector))
		 {
			 /* mark rule as being relevant to this sentence */
			 pp->relevant_contains_one_rules[rcoIDX++] = coIDX;
			 pp_linkset_add(pp->set_of_links_in_an_active_rule, rule->selector);
		 }
		 }
	 pp->relevant_contains_one_rules[rcoIDX] = -1;	/* end sentinel */

	 for (cnIDX=0;;cnIDX++)
		 {
			 rule = &(pp->knowledge->contains_none_rules[cnIDX]);
			 if (rule->msg==NULL) break;
			 if (pp_linkset_match_bw(pp->set_of_links_of_sentence, rule->selector))
		 {
			 pp->relevant_contains_none_rules[rcnIDX++] = cnIDX;
			 pp_linkset_add(pp->set_of_links_in_an_active_rule, rule->selector);
		 }
	 }
	 pp->relevant_contains_none_rules[rcnIDX] = -1;

	 if (verbosity>1) {
		 printf("Saw %i unique link names in all linkages.\n",
				pp_linkset_population(pp->set_of_links_of_sentence));
		 printf("Using %i 'contains one' rules and %i 'contains none' rules\n",
				rcoIDX, rcnIDX);
	 }
}

/***************** definitions of exported functions ***********************/

/**
 * read rules from path and initialize the appropriate fields in
 * a postprocessor structure, a pointer to which is returned.
 */
Postprocessor * post_process_open(char *path)
{
	Postprocessor *pp;
	if (path==NULL) return NULL;

	pp = (Postprocessor *) xalloc (sizeof(Postprocessor));
	pp->knowledge	= pp_knowledge_open(path);
	pp->sentence_link_name_set = string_set_create();
	pp->set_of_links_of_sentence = pp_linkset_open(1024);
	pp->set_of_links_in_an_active_rule=pp_linkset_open(1024);
	pp->relevant_contains_one_rules =
			(int *) xalloc ((pp->knowledge->n_contains_one_rules+1)
							*(sizeof pp->relevant_contains_one_rules[0]));
	pp->relevant_contains_none_rules =
			(int *) xalloc ((pp->knowledge->n_contains_none_rules+1)
							*(sizeof pp->relevant_contains_none_rules[0]));
	pp->relevant_contains_one_rules[0]	= -1;
	pp->relevant_contains_none_rules[0] = -1;
	pp->pp_node = NULL;
	pp->pp_data.links_to_ignore = NULL;
	pp->n_local_rules_firing	= 0;
	pp->n_global_rules_firing = 0;
	return pp;
}

void post_process_close(Postprocessor *pp)
{
	/* frees up memory associated with pp, previously allocated by open */
	if (pp==NULL) return;
	string_set_delete(pp->sentence_link_name_set);
	pp_linkset_close(pp->set_of_links_of_sentence);
	pp_linkset_close(pp->set_of_links_in_an_active_rule);
	xfree(pp->relevant_contains_one_rules,
		(1+pp->knowledge->n_contains_one_rules)
		*(sizeof pp->relevant_contains_one_rules[0]));
	xfree(pp->relevant_contains_none_rules,
		(1+pp->knowledge->n_contains_none_rules)
		*(sizeof pp->relevant_contains_none_rules[0]));
	pp_knowledge_close(pp->knowledge);
	free_pp_node(pp);
	xfree(pp, sizeof(Postprocessor));
}

void post_process_close_sentence(Postprocessor *pp)
{
	if (pp==NULL) return;
	pp_linkset_clear(pp->set_of_links_of_sentence);
	pp_linkset_clear(pp->set_of_links_in_an_active_rule);
	string_set_delete(pp->sentence_link_name_set);
	pp->sentence_link_name_set = string_set_create();
	pp->n_local_rules_firing	= 0;
	pp->n_global_rules_firing = 0;
	pp->relevant_contains_one_rules[0]	= -1;
	pp->relevant_contains_none_rules[0] = -1;
	free_pp_node(pp);
}

void post_process_scan_linkage(Postprocessor *pp, Parse_Options opts,
									 Sentence sent, Sublinkage *sublinkage)
{
	/* During a first pass (prior to actual post-processing of the linkages
		 of a sentence), call this once for every generated linkage. Here we
		 simply maintain a set of "seen" link names for rule pruning later on */
	char *p;
	int i;
	if (pp==NULL) return;
	if (sent->length < opts->twopass_length) return;
	for (i=0; i<sublinkage->num_links; i++)
		{
			if (sublinkage->link[i]->l == -1) continue;
			p=string_set_add(sublinkage->link[i]->name,pp->sentence_link_name_set);
			pp_linkset_add(pp->set_of_links_of_sentence, p);
		}
}

/**
 * Takes a sublinkage and returns:
 *  . for each link, the domain structure of that link
 *  . a list of the violation strings
 * NB: sublinkage->link[i]->l=-1 means that this connector
 * is to be ignored
 */
PP_node *post_process(Postprocessor *pp, Parse_Options opts,
							Sentence sent, Sublinkage *sublinkage, int cleanup)
{
	char *msg;

	if (pp==NULL) return NULL;

	pp->pp_data.links_to_ignore = NULL;
	pp->pp_data.length = sent->length;

	/* In the name of responsible memory management, we retain a copy of the
	 * returned data structure pp_node as a field in pp, so that we can clear
	 * it out after every call, without relying on the user to do so. */
	reset_pp_node(pp);

	/* The first time we see a sentence, prune the rules which we won't be
	 * needing during postprocessing the linkages of this sentence */
	if (sent->q_pruned_rules==FALSE && sent->length >= opts->twopass_length)
		prune_irrelevant_rules(pp);
	sent->q_pruned_rules=TRUE;

	switch(internal_process(pp, sublinkage, &msg))
	{
		case -1:
			/* some global test failed even before we had to build the domains */
			pp->n_global_rules_firing++;
			pp->pp_node->violation = msg;
			return pp->pp_node;
			break;
		case 1:
			/* one of the "normal" post processing tests failed */
			pp->n_local_rules_firing++;
			pp->pp_node->violation = msg;
			break;
		case 0:
			/* This linkage is legal according to the post processing rules */
			pp->pp_node->violation = NULL;
			break;
	}

	build_type_array(pp);
	if (cleanup)
	{
		post_process_free_data(&pp->pp_data);
	}
	return pp->pp_node;
}

/*
	string comparison in postprocessing. The first parameter is a
	post-processing symbol. The second one is a connector name from a link. The
	upper case parts must match. We imagine that the first arg is padded with an
	infinite sequence of "#" and that the 2nd one is padded with "*". "#"
	matches anything, but "*" is just like an ordinary char for matching
	purposes. For efficiency sake there are several different versions of these
	functions
	*/

int post_process_match(const char *s, const char *t)
{
	char c;
	while(isupper((int)*s) || isupper((int)*t))
		{
			if (*s != *t) return FALSE;
			s++;
			t++;
		}
	while (*s != '\0')
		{
			if (*s != '#')
		{
			if (*t == '\0') c = '*'; else c = *t;
			if (*s != c) return FALSE;
		}
			s++;
			if (*t != '\0') t++;
		}
	return TRUE;
}

/* OLD COMMENTS (OUT OF DATE):
  This file does the post-processing.
  The main routine is "post_process()".  It uses the link names only,
  and not the connectors.

  A domain is a set of links.  Each domain has a defining link.
  Only certain types of links serve to define a domain.  These
  parameters are set by the lists of link names in a separate,
  human-readable file referred to herein as the 'knowledge file.'

  The domains are nested: given two domains, either they're disjoint,
  or one contains the other, i.e. they're tree structured.  The set of links
  in a domain (but in no smaller domain) are called the "group" of the
  domain.  Data structures are built to store all this stuff.
  The tree structured property is not mathematically guaranteed by
  the domain construction algorithm.  Davy simply claims that because
  of how he built the dictionary, the domains will always be so
  structured.  The program checks this and gives an error message
  if it's violated.

  Define the "root word" of a link (or domain) to be the word at the
  left end of the link.  The other end of the defining link is called
  the "right word".

  The domain corresponding to a link is defined to be the set of links
  reachable by starting from the right word, following links and never
  using the root word or any word to its left.

  There are some minor exceptions to this.  The "restricted_link" lists
  those connectors that, even if they point back before the root word,
  are included in the domain.  Some of the starting links are included
  in their domain, these are listed in the "domain_contains_links" list.

  Such was the way it was.  Now Davy tells me there should be another type
  of domain that's quite different.  Let's call these "urfl" domains.
  Certain type of connectors start urfl domains.  They're listed below.
  In a urfl domain, the search includes the root word.  It does a separate
  search to find urfl domains.

  Restricted links should work just as they do with ordinary domains. If they
  come out of the right word, or anything to the right of it (that's
  in the domain), they should be included but should not be traced
  further. If they come out of the root word, they should not be
  included.
  */

/*
  I also, unfortunately, want to propose a new type of domain. These
  would include everything that can be reached from the root word of the
  link, to the right, that is closer than the right word of the link.
  (They would not include the link itself.)

  In the following sentence, then, the "Urfl_Only Domain" of the G link
  would include only the "O" link:

  +-----G----+
  +---O--+   +-AI+
  |      |   |   |
  hitting dogs is fun.a

  In the following sentence it would include the "O", the "TT", the "I",
  the second "O", and the "A".

  +----------------G---------------+
  +-----TT-----+  +-----O-----+    |
  +---O---+    +-I+    +---A--+    +-AI+
  |       |    |  |    |      |    |   |
  telling people to do stupid things is fun.a

  This would allow us to judge the following:

  kicking dogs bores me
  *kicking dogs kicks dogs
  explaining the program is easy
  *explaining the program is running

  (These are distinctions that I thought we would never be able to make,
  so I told myself they were semantic rather than syntactic. But with
  domains, they should be easy.)
  */

  /* Modifications, 6/96 ALB:
     1) Rules and link sets are relegated to a separate, user-written
        file(s), herein referred to as the 'knowledge file'
     2) This information is read by a lexer, in pp_lexer.l (lex code)
        whose exported routines are all prefixed by 'pp_lexer'
     3) when postprocessing a sentence, the links of each domain are
        placed in a set for quick lookup, ('contains one' and 'contains none')
     4) Functions which were never called have been eliminated:
        link_inhabits(), match_in_list(), group_type_contains(),
        group_type_contains_one(),  group_type_contains_all()
     5) Some 'one-by-one' initializations have been replaced by faster
        block memory operations (memset etc.)
     6) The above comments are correct but incomplete! (1/97)
     7) observation: the 'contains one' is, empirically, by far the most
        violated rule, so it should come first in applying the rules.

    Modifications, 9/97 ALB:
     Deglobalization. Made code constistent with api.
   */